透過 gcc 展開 macro 會得到以下結果
mask 是避免使用者輸入 > bits 數的數字,同時可以省掉一個 if
如果沒有 mask ,就需要用 if 寫成這樣
以 184 (隨機選的 8bits 數字)為例
184 的 bits 是 : 10111000
假設向左 rotate 2 個 bits
(v << c) 會變成 111000
那最前面的 10 會移到最後面變成 000000 10
假設向左 rotate 4 個 bits
最前面的 1011 會移到最後面變成 0000 1011
假設向左 rotate 6 個 bits
最前面的 101110 會移到最後面變成 00 101110
透過觀察可以看到, overflow 的部分其實是等同於做反向的 shift
而這個 bits 數會是最大 bits 減去使用者輸入的數字
所以答案是 (v <反向> (bits-c))
根據文章表示,這樣的寫法需要去處理額外 0 的部分,因為當 rotate 為 0 時,bits 會全部 rotate 一輪,這樣會有額外運算.所以用個 if 去判斷是否為 0,不過這樣在 assembly 就會產生 branch
答案
要理解這樣的方式,需要先理解補數: 解讀計算機編碼-計算機為何如此編碼
uintptr_t : 任意數字
alignment : 要對齊的數字
假設要對齊的數字是 4
那輸入的數字跟相對應的結果就會如以下
關於 memory alignment 可以參考以下文章
memory alignment
參考來自 boost source code 1.68.0 : https://www.boost.org/doc/libs/1_68_0/boost/align/align_up.hpp
如果是 power of 2 , 假設 alignment 為 8
可以把
看成
簡單來說就會是對後面 3 個 bits 直接清 0
如果是後面 3 個 bits 清成 0 則可以產生類似這樣的 mask (假設為 mask0)
mask0 則會等於 alignment 減一 再取個 not
再取個 not
這樣就可以完成新的 mask0 然後去做 alignment.
先要理解 fork 跟 fflush 怎麼運作
透過測試的結果是 12
依照這篇 stackoverflow 上面說的,兩個情形照成多印出來的狀況
\n
再印出 或 flush(清空)不過以上的說法還需要實際驗證,但跟目前輸出的情形雷同
AAA 是在 con_push 裡面.
這個 function 是把新的值加到 queue 裡面,
AAA 的部分則是把 node 加到 queue 的後面
BBB 跟 CCC 是在 con_pop 裡面
這個 function 主要是從 queue 中 pop 一個數字
BBB 是把值給 return_value
CCC 則是做移動 first 的部分
iceil2 這個 function 主要是在找最高位的 bit
策略就是把高位的 bits 1 複製到低位的 bit 讓數字變成全部都是1
最後再 + 1 進行進位,來找到 ceil
所以以下的過程是在進行一個 bits 複製的動作
以 4097 為例
首先先減 1 變為 4096, 然後進行最前面第一個 bit 複製
先 shit 1 得到要複製的 bit
因為已經有兩個 bits 了所以直接複製兩個
現在有 4 個 bits 所以可以直接複製 4 個
因為有 8 個 bits 為 1 了,所以可以一次複製 8 個
16個的結果是一樣的,所以不變,最後再做 +1 來取得 ceil (天花板)
所以就會得到 8192
答案來自這個 github repo
透過 gdb 可以知道 mp->hs[i] 會被換成 p 的 address
然後新的 address 的 value 會是原本的 address
經過幾輪的 repool 再透過 x 去 dump memory
可以發現前幾輪的 memory address 裡面的值是之前的 address
但是再多做幾輪就會發現前幾次 address 中的直變成 9 (這邊我把程式的 p 從 7 改成 9)
LLL 跟 JJJ 是設定 poll 的 fd 跟要觸發的 events
以題目為例是只設定 POLLIN
然後從這段程式碼可以知道 pollsp[0] 是放 cl_fd
所以答案如下