contributed by < ofAlpaca
>
CSIE5006
HW
1
考慮以下程式碼:
在 GNU/Linux x86_64 環境中執行,得到以下輸出:
倘若將第 10 和第 11 換為以下:
會發生什麼事?
編譯失敗,不能將指標指向沒有對齊 1 byte 的結構體成員;
延伸問題: 解釋原因,並且找出 C99/C11 規格書對應的描述
&
operator 。
C99 [3.2] alignment
requirement that objects of a particular type be located on storage boundaries with addresses that are particular multiples of a byte address.
C99 [6.7.2.1] The unary & (address-of) operator cannot be applied to a bit-field object; thus, there are no pointers to or arrays of bit-field objects.
sizeof(S)
不會是 1 + 4 = 5 而是 8 ,這是為了 access memory 時能更加有效率, struct member 是會自動對齊的。z
的 offset 是 &z - &S = 4 。struct test
來看,其 structure alignment 應該會是 :z
的 offset 為 0x0004 - 0x0000 = 4 。2
考慮以下程式碼,在 little-endian 硬體上,會返回 1
,反之,在 big-endian 硬體上會返回 0
:
補完上述程式碼。
K1 = ?
1
K2 = ?
1
延伸問題: 解釋運作原理,並找出類似的程式碼
char * c
還讀得到 ; 相反的,如果是 big endian , 0x01 這個 byte 會被放在高位址, char * c
的範圍只有 1 byte ,因此就讀不到了。3
以下程式碼計算 parity bit:
補完程式碼
P=28
延伸問題: 解釋原理,並且提出更快的實作機制 (提示: 透過 SIMD)
第一次看的時候會嚇到,但是深入了解後會發現其觀念蠻簡單的,先有個概念,以 nibble(4-bits) 為單位,用 shift 與 XOR 來判斷此 nibble 是奇同位還是偶同位,最後再將所有 nibble 相加並取其 LSB ,若是 1 則為奇同位 0 則為偶同位。
x ^= x >> 1
與 x ^= x >> 2
是先用 shift 來將 nibble 內的每個 bit 重疊在一起,並透過 XOR 的特性來達到兩兩消除 b'1
的效果,如 b'1 XOR b'1 = b'0
,如果最後 nibble 的 LSB 是 1 則是奇同位 0 則是偶同位, 32 bits 總共會有 8 組 nibbles 。x = (x & 0x11111111U) * 0x11111111U
此行的目的便是先取出所有 nibble 的 LSB 並相加在一起,並取得後面的 32 bits。(x >> 28) & 1
最後再 shift right 28 bits 得到所有 nibble 相加後結果,再取其 LSB 便得到了 x 的 parity bit 了。SIMD
後來找到 bit-interleave(SIMD ver) 與 SIMD Example 於是想嘗試看看能不能使用 AVX 指令集來作到 parity check 。
2
指標篇 提到 signal 系統呼叫的原型宣告:
該如何解析呢?
提示: 參閱 manpage: signal(2)
延伸問題: 解釋 signal(2) 的作用,並在 GitHub 找出應用案例
解析 :
signal(int sig, void (*handler)(int))
有兩個參數, int 與有著 int 參數返回 void 的 function pointer , signal 為函式名稱。void (*signal(int sig, void (*handler)(int))) (int)
則是需要 int 參數並回傳 void 的 function pointer 。[x]signal(2)
signal(2)
函式提供了一個可以處理非同步事件的方法。
sig
為 signal number ,為中斷的編號,定義在 C 函式庫的 signal.h
裡,變數是 SIG 開頭,像是 SIGINT
、 SIGSEGV
。handler
可以有三種值 :
SIG_IGN
,訊號忽略。SIG_DFL
,訊號會照預設情況處理。handler
就會被呼叫,此稱為 signal handler 或 signal-catching function。handler
所傳入的參數即是 signal number 。SIGKILL
與 SIGSTOP
不能被忽略或是 catch 。signal
來處理中斷訊息如 :SigHand()
則為 :5
以下程式是合法 C99 程式嗎?
請搭配 C 語言規格書解釋
繼續思考以下是否合法:
繼續變形:
也會合法嗎?為什麼?請翻閱 C 語言規格書解說。
int t()
的 function designator 會變成 int (*t) ()
的 pointer to function 。
C99 [6.3.2.1] A function designator is an expression that has function type. Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type ‘‘function returning type ’’ is converted to an expression that has type ‘‘pointer to function returning type ’’.
put()
是個 function designator ,所以會被轉為 pointer to function :
*put()
,在前面加上 dereference of (*
) 會使 pointer to function 變成 function designator ,但會再被轉回 pointer to function 。&put()
,在前面加上 address of (&
) 會讓原本的 function designator 變為 pointer to function 。put()
前怎麼加 *
或 &
最終的結果都是 pointer to function 。