C 語言中 sizeof 與 strlen 的區別是經典考點,結合八進制轉義序列的編譯器解析規則,更能考察對字符串字面量內存佈局的理解。本文詳細解析 "\La\016ef" 與 "\La\018ef" 的 sizeof 差異根因。
char str[] = "\La\016ef";
printf("%d\n", sizeof(str)); // 輸出 6
char str2[] = "\La\018ef";
printf("%d\n", sizeof(str2)); // 輸出 7
| 運算符/函數 | 計算對象 | 包含結束符 | 計算時機 |
|---|---|---|---|
sizeof(str) | 數組總字節數 | ✅ 是 | 編譯期 |
strlen(str) | 字符串有效長度 | ❌ 否 | 運行期 |
關鍵:sizeof 返回數組定義時分配的總字節數,包含編譯器自動添加的 '\0'。
八進制轉義序列
\ddd:最多 3 位八進制數字 (0-7),編譯器貪婪匹配盡可能多的合法八進制數字。
"\La\016ef" → sizeof = 6
源碼字符序列: \ L a \ 0 1 6 e f
編譯器解析: \L a \016 e f
│ │ │ │ │
│ │ │ │ └─ 字符 'f' (1 個字節)
│ │ │ └──── 字符 'e' (1 個字節)
│ │ └──────── 八進制 016 = 十進制 14 (1 個字節)
│ └──────────── 字符 'a' (1 個字節)
└──────────────── 未定義轉義 \L → 視為 'L' (1 個字節,GCC 警告)
字節序列: 'L'(4C) 'a'(61) 0x0E 'e'(65) 'f'(66) '\0'(00)
索引: 0 1 2 3 4 5
總計 6 字節 (含結束符) → sizeof = 6
"\La\018ef" → sizeof = 7
源碼字符序列: \ L a \ 0 1 8 e f
編譯器解析: \L a \01 8 e f
│ │ │ │ │ │
│ │ │ │ │ └─ 'f'
│ │ │ │ └──── 'e'
│ │ │ └────── 字符 '8' (非八進制,單獨字節)
│ │ └────────── 八進制 01 = 十進制 1 (1 字節)
│ └────────────── 'a'
└────────────────── \L → 'L'
字節序列: 'L' 'a' 0x01 '8' 'e' 'f' '\0'
索引: 0 1 2 3 4 5 6
總計 7 字節 → sizeof = 7
| 源碼片段 | 解析結果 | 字節數 | 原因 |
|---|---|---|---|
\016 | 八進制 016 (十進制 14) | 1 | 3 位合法八進制數字 |
\018 | 八進制 01 (十進制 1) + 字符 '8' | 2 | 8 非八進制,貪婪匹配停止 |