應用場景
內存對齊時基本都會求關於n位對齊的向上取整
講解
go1.13.8 中channel源碼中有這樣一個變量hchansize用來表示hchan(channel對應的實際結構體)所需大小(申請內存空間時,是根據hchansize給hchan申請對應大小的內存空間),這個變量的值大概就是hchan的size關於maxAlign向上取整下一個較大倍數,看到源碼實現時,就感覺真是怪物。
hchanSize = unsafe.Sizeof(hchan{}) + uintptr(-int(unsafe.Sizeof(hchan{}))&(maxAlign-1))
為了方便將上述表達式簡化為 n + ( (-n) & (a - 1)),n是unsafe.Sizeof(hchan{}),a是maxAlign。等價於 n + (a - (n % a))
( (-n) & (a - 1) ) 等價 a - (n % a) ?
向上取整的問題實際可以轉化為求出n距離下一個a的倍數差多少,然后n加上這個數就可以。
當a為2的n次冪時,n % a可以轉化為 n & (a - 1),取模運算就變成了n與(a - 1) AND時能留下多少個1。
計算機實際計算時是以補碼進行運算的,-n轉化為補碼,符號位不變其他位取反轉化為反碼,然后最低位+1轉化為補碼,下面分兩步講。
以n = 3, a = 8為例(實際計算時是8字節,下面用一字節舉例):
原碼: -n = 1000 0011
反碼: -n = 1111 1100
此時(-n) & (a - 1)實際為 (a - 1) - n % a,而咱們要求的是a - (n % a)
補碼:-n = 1111 1101
因為-n的反碼變補碼時最低位要+1,所以剛好(a - 1) - n % a + 1 = a - (n % a)
所以( (-n) & (a - 1) ) 等價 a - (n % a)