contributed by < Chao-Shun-Cheng
>
1
首先可以觀察到 ~0UL
是 0xffffffffffffffff
,另外左半邊只有邏輯右移,因此可以推斷左半邊就是製造出高位的 bitmask
。舉例來說,假如 h
是 60,那就代表高位的 bitmask
會是 0x0fffffffffffffff
,因此可以推測出 LEFT
就是 63 - h
。再來右邊就是要製造出低位的 bitmask
,假如說 l
是 5,那 bitmask
就是 0xfffffffffffffff0
,因此可以推測出 RIGHT
就是 l
。
我認為右移 l
是多餘的,不影響結果
2
參考 jim12312321
同學對於 data alignment 的解說以及Stackoverflow 的解說。其中有一個關鍵的地方 : Sequential addresses refer to sequential bytes in memory.
還沒看到這句的時候實在不懂 jim12312321
同學的意思,直到看到這個才豁然開朗。
主要就是要將最後兩個 bits 設為 0 ,另外可以觀察到 EXP1
要傳入的型態是 struct foo *
,因此可以推測會用到型態轉換。因此可以得知 EXP1
就是 (struct foo *)(v & ~3)
。
3
首先可以先觀察第 4 行,會把前 4 個與後 4 個 bit
進行交換。
因此可以猜測第 5 行就是兩個 bit
一組,去進行交換;第 6 行就是一個 bit
一組進行交換。另外 0xCC
就是 11001100
,可以猜測出另一邊的 bitmask
要是 00110011
,因此 EXP2
就是 (x & 0x55) << 2
。0xAA
則是 10101010
,可以猜測出另一邊的 bitmask
就是 01010101
,因此 EXP3
就是 (x & 0x33) << 1
。
4
主要參考 kevinshieh0225
同學的解說
不難發現 foreach_ptr
與 foreach_int
是要把所有參數的內容指定到 i
裡面。第 6 行把 _foreach_i
當作是 index
;第 7 行則去判斷有沒有超過參數範圍;最後第 8 行就是把第 index
裡的值 assign 到 i
並且進行 index++
,因此可以推斷出 EXP4
就是 _foreach_i++
。同理,EXP5
也是 _foreach_i++
。
5
首先可以看到 4 ~ 15 行賄先把除數跟被除數都先轉換成正數,並將結果的正負號存在 singal
這個變數當中。
接下來看到第 18 行的 while
迴圈,會找出除數往左 shift
幾次後會比被除數大,因此可以推測出 EXP6
就是 dvs << shift
。
第 22 行的 while
迴圈會去看除數是不是比被除數小,假如比較小才需要繼續計算。最後 23 ~ 26 行則是透過 shift
找出商,並減去轉成傷的部分。因此可以推測出 EXP7
就是 dvd - dvs << shift
。
7
首先可以看到第 4 行,去判斷從左數來的 16 個 bits 有無 1,如果有就把結果存進去 ret
並且繼續看這 16 個 bits ( 對應到第 5 行);第 7 行則是從這 16 個 bits 繼續去看從左數來的 8 個 bits,然後進行一樣的操作。因此可以推測出 EXP10
會是 (v > 0x3U) << 1
。
可以觀察到 0xFFFFU
是 16 個 bits;0xFFU
是 8 個 bits;0xFU
是 4 個 bits;0x3U
是 2 個 bits。因此還要討論最後一個 bit,因此可以推測出 EXP11
會做出以下程式碼的行為,不過是濃縮成一行
因此可以知道 EXP11
就是 ret |= (v > 0x1U)
8
可以先參考二叉搜尋樹刪除所提及的刪除方法,會方便理解二元數的刪除原理。
首先可以看到第 4 行的 while
迴圈,會在這個迴圈找到要刪除的 node
,這邊使用指標的指標,可以找到要刪除的 node
以及他的 parent
。可以知道 EXP12
是要往左邊走,EXP13
是要往右邊走,因此 EXP12
就是 p = &(*p)->left
;EXP13
就是 p = &(*p)->right
。
接下來就是要討論三種刪除的可能性,首先是要刪除的 node
沒有左子樹;再來是要刪除的 node
沒有右子樹,相對應的操作在 14 ~ 17 行;最後就是有左右子樹,因此只要將右子樹中最小值搬到要刪除的 node
位置。可以推測出 20 行的 while
迴圈是要找出右子樹中的最小值,因此 EXP14
就是 &(*r)->left
。
9
主要參考 kevinshieh0225
同學的解說
首先可以看到是要做出 16 的倍數,因此 address 的最後 4 個 bit 要可以為 0,因此可以先推測出 NNN
就是 MAX_ALIGMENT - 1
。另外由於是向上對齊,所以不足 16 倍數的則要補上去,因此可以猜測出 MMM
就是 1
。
10
首先可以看到第 5 行的條件式,主要是用來判斷除數跟被除數是不是均為正數,另外就是利用 typeof
去看型態是不是 unsigned
。假如符合條件就會進行第一個操作 ((RRR) / (__d))
,不符合的話就會進行 ((SSS) / (__d))
。
回顧本題目就是要進行四捨五入的操作,其中可以觀察到第 7 行的 /
在 c 語言當中是無條件捨去,因此要作一些對應的操作使其符合四捨五入的原則。
因此可以推測出 RRR
就是 __x + (__d >> 1)
。另外若有負數的話就要進行減,因此 SSS
就是 __x - (__d >> 1)
。