[c]
#include
int main(void) {
char* p = NULL;
char* tmp = "12345678";
p = (char*)(tmp + 4); // p 指向 '5' (索引4)
// p[-1] = ? p[-5] = ?
printf("p[-1] = %c, p[-5] = %c\n", p[-1], p[-5]);
return 0;
}
答案:p[-1] = '4', p[-5] = '1'。
原理:p[-n] ≡ *(p - n) ≡ p[n] (指標算術對稱性)。tmp+4 指向第 5 個字元 '5',往前 1 位是 '4',往前 5 位是 '1'。
[c]
#include
#include
int main(void) {
char* data = "12345678";
short* tmp = NULL;
char p[6] = {0};
tmp = (short*)&p[2]; // 將 p[2]、p[3] 視為一個 short
*tmp = atoi(&data[4]); // atoi("5678") = 5678 = 0x162E
// p[0]~p[5] = ?
for (int i = 0; i < 6; i++) printf("p[%d] = %d (0x%02X)\n", i, p[i], (unsigned char)p[i]);
return 0;
}
答案 (小端機 x86/ARM):
| 索引 | 值 (十進制) | Hex | 說明 |
|---|---|---|---|
| p[0] | 0 | 0x00 | 未觸動 |
| p[1] | 0 | 0x00 | 未觸動 |
| p[2] | 46 | 0x2E | 5678 低位元組 |
| p[3] | 22 | 0x16 | 5678 高位元組 |
| p[4] | 0 | 0x00 | 未觸動 |
| p[5] | 0 | 0x00 | 未觸動 |
核心考點:類型懲罰 違反嚴格別名規則,行為未定義;端序 決定多位元組寫入順序;對齊:&p[2] 可能未 2 位元組對齊,部分架構會觸發 SIGBUS。
[c]
int* p = (int*)0x1234;
printf("p = %p, *p = %d\n", p, *p);
結果:未定義行為 (UB),極大機率 **Segmentation Fault (段錯誤)**。
原因:0x1234 非用戶態合法映射地址 (通常在第一個頁面 0x0~0xFFF 為守護頁,或屬於內核/未映射區)。解引用觸發頁錯誤,OS 發送 SIGSEGV 終止進程。
教訓:永遠不要解引用未經驗證的任意數值指標。嵌入式裸機編程中訪問硬體寄存器需用 volatile uint32_t *reg = (volatile uint32_t*)0x40000000; 並確保地址合法映射。
p + n 按 sizeof(*p) 縮放,負索引同理。char* 別名例外允許訪問任意類型,但反向 (short* 寫 char[]) 違規。short* 需 2 字節對齊,int* 需 4 字節對齊。