Try   HackMD

課程教材疑惑及洞見

前置處理器應用篇

對應教材:前置處理器應用篇

#define STRING_SWITCH_L(s) \
    switch (*((int32_t *)(s)) | 0x20202020)
#define MULTICHAR_CONSTANT(a,b,c,d) \
    ((int32_t)((a) | (b) << 8 | (c) << 16 | (d) << 24))

教材 bitwise 操作 講到 ASCII 編碼英文大寫字母與小寫相隔 32,即 2 的 5 次方,在這裡可以看到 STRING_SWITCH_L 巨集的操作 | 0x20202020 的行為就等同於將每個位元組的字母統一轉為小寫。

紅黑樹

對應教材:Linux 核心的紅黑樹

  • 疑惑: 指標最低的兩個位元一定不會使用到?

紅黑樹節點
透過 attribute((aligned(sizeof(long)))) 讓編譯器知道 struct rb_node 會對齊 sizeof(long),這樣就會讓指標最低 2 個位元是沒有使用到的,就可以把顏色的資料放進去其中一個位元中。
舉例來說,一個節點指標如果指向 0xF724315C ,這個位址轉成二進位會變成 1100,最低 2 個位元會是 0,Linux 核心開發者利用這特性,將其中一個沒用到的位元拿來標注紅和黑這二種顏色。

回頭看 你所不知道的 C 語言:記憶體管理、對齊及硬體特性 之後才知道以 long 做對齊讓連續記憶體位置間隔為 8 (取決於 long 的大小),所以真得不會使用到最低的兩個位元。在#標示不用的節點章節中有針對此問題做解說。

  • x86-64 ABI : Aggregates and Unions

Structures and unions assume the alignment of their most strictly aligned component. Each member is assigned to the lowest available offset with the appropriate alignment. The size of any object is always a multiple of the object‘s alignment.
An array uses the same alignment as its elements, except that a local or global array variable of length at least 16 bytes or a C99 variable-length array variable always has alignment of at least 16 bytes.
Structure and union objects can require padding to meet size and alignment
constraints. The contents of any padding is undefined.

翻閱 x86-64 ABI,以確認上述說法。