目的: 檢驗學員對 C 語言 pointer, union, bit-fields, 實作 linked list 的認知
1
考慮以下程式碼:
#include <stdio.h>
#include <stdint.h>
struct test {
unsigned int x : 5;
unsigned int y : 5;
unsigned int z;
};
int main() {
struct test t;
printf("Offset of z in struct test is %ld\n",
(uintptr_t) &t.z - (uintptr_t) &t);
return 0;
}
在 GNU/Linux x86_64 環境中執行,得到以下輸出:
Offset of z in struct test is 4
倘若將第 10 和第 11 換為以下:
printf("Address of t.x is %p", &t.x);
會發生什麼事?
作答區
(a)
印出類似 0x7ffd144e8ad4
的輸出,也就是 t
結構物件的位址;(b)
印出類似 0x7ffd144e8ad4
的輸出,和 t
結構物件差距 4 bytes;(c)
可以印出數值,但這與編譯器實作有關,不能解讀;(d)
編譯失敗,不能這樣宣告結構體的成員;(e)
編譯失敗,不能將指標指向沒有對齊 1 byte 的結構體成員;參考資料: Portable Bit Fields in packetC
延伸問題: 解釋原因,並且找出 C99/C11 規格書對應的描述
2
考慮以下程式碼,在 little-endian 硬體上,會返回 1
,反之,在 big-endian 硬體上會返回 0
:
int main() {
union { int a; char b;
} c = { .a = K1 };
return c.b == K2;
}
補完上述程式碼。
作答區
K1 = ?
(a)
0(b)
1(c)
-1(d)
254K2 = ?
(a)
0(b)
1(c)
254延伸問題: 解釋運作原理,並找出類似的程式碼
3
以下程式碼計算 parity bit:
#include <stdint.h>
int parity(uint32_t x)
x ^= x >> 1;
x ^= x >> 2;
x = (x & 0x11111111U) * 0x11111111U;
return (x >> P) & 1;
}
補完程式碼
作答區
P = ?
(a)
32(b)
31(c)
30(d)
29(e)
28(f)
27(g)
26(h)
25(i)
24延伸問題: 解釋原理,並且提出更快的實作機制 (提示: 透過 SIMD)
4
考慮以下程式碼:
#include <stdlib.h>
#include <string.h>
typedef struct rec {
char *value;
struct rec *next;
} record;
void insert_sorted(record **r, const char *value)
{
record *newrec = NULL;
while (*r && strcmp(value, (*r)->value) > 0)
r = &((F1)->next);
newrec = malloc(sizeof(record));
newrec->value = F2(value);
newrec->next = F3;
F4 = newrec;
}
函式 insert_sorted
的作用是在 r 所指向已依據數值排序的 linked list 中,安插給定的字串,考慮到 string literal 的生命週期,應該在新建立的節點中,複製給定的字串。
請補完上述程式碼。
作答區
F1 = ?
(a)
r(b)
**r(c)
*r(d)
r->next(e)
*r->nextF2 = ?
(a)
無(b)
strdup(c)
strcpy(d)
strlen(e)
strcmpF3 = ?
(a)
r(b)
**r(c)
*r(d)
r->next(e)
*r->nextF4 = ?
(a)
**r(b)
*r(c)
r(d)
r->next(e)
*r->next延伸問題: 解釋運作原理,並新增刪除和搜尋節點的程式,附上完整的測試計畫