contributed by < KJay221
>
1
GENMASK
巨集,微處理器架構為 64 位元
63-h
l
以 GENMASK(6, 4)
產生01110000
為例,首先可以先將 GENMASK
看成 a & b
a
的部份只有11111111
向右位移,可推測 a
為01111111
,所以 LEFT
為 (8-(6+1))
,若是64位元的話則為 64-(h+1) = 63-h
若 a & b
要得到正確答案01110000
推測 b
為11110000
,所以 b
要先右移 l
再左移 l
才會得到正確答案
GENMASK
巨集的實作,闡述其額外的考量GENMASK
巨集和 include/linux/bitfield.h 的應用案例2
考慮以下程式碼:
EXP1
= (struct foo *)(v & ~3)
若 struct fd
中的 struct foo *foo
要對 4 個位元組進行向下對齊,則其 bit0、bit1
必為 0,當傳入的地址 v
要向下對齊時,只要用 v & ~3
就能清空 bit0、bit1
達到對齊效果,又因應回傳型態的要求,要在前面加上 (struct foo *)
來強制轉型結果才會是正確的
3
考慮以下程式碼,能將輸入的 8 位元無號整數逐一位元反轉
EXP2
= (x & 0x33) << 2
EXP3
= (x & 0x55) << 1
參考 < hsuedw > 的圖示和 你所不知道的 C 語言:數值系統篇
4bits
切成兩組並左右交換,接著這兩組 4bits
又各自再切成兩組 2bits
然後也左右交換,一直重複做到切成 1bits
為止32bits
則一開始則切成兩個 16bits
依此類推4
延伸〈你所不知道的 C 語言:前置處理器應用篇〉,我們嘗試將 foreach 巨集 予以擴充,使得支援以下寫法:
預期輸出如下:
對應的巨集定義:
EXP4
= ++_foreach_i
EXP5
= ++_foreach_i
參考 < hsuedw > 對於 __VA_ARGS__
的解釋得出 foreach_int(i, ...)
主要的三個動作
unsigned _foreach_i = (((i) = ((int[]){__VA_ARGS__})[0]), 0);
將 _foreach_i
初始化為零,並將 i
設成輸入的第 0
個元素_foreach_i < sizeof((int[]){__VA_ARGS__}) / sizeof(int);
為測試 _foreach_i
是否超出範圍(i) = ((int[]){__VA_ARGS__, 0})[++_foreach_i])
的功能為將 i
設成當前索引值所對應的元素並將 _foreach_i
加一,另外用 ++_foreach_i
則是為了先將 _foreach_i
加一,再更新 i
的內容5
針對 LeetCode 29. Divide Two Integers,以下是可能的實作:
EXP6
= dvs << shift
EXP7
= dvd -= dvs << shift
上述的程式碼運作邏輯與硬體除法器的概念相似,首先在 4~15 行的部分,先將正號決定好,並將負數轉成正數以便後面實現正數除法,17~27 行的部分則是做除法,並將結果儲存於 res
中,最後將 res
與 signal
相乘即是結果
6
針對 LeetCode 149. Max Points on a Line,以下是可能的實作:
EXP8
= ans
EXP9
= ans