首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言 sizeof 與 strlen 差異:八進制轉義導致的字符串長度計算陷阱

     編輯:程式設計綜合問答

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'。

八進制轉義解析規則 (C99 6.4.4.4)

八進制轉義序列 \ddd:最多 3 位八進制數字 (0-7),編譯器貪婪匹配盡可能多的合法八進制數字。

逐字符解析對比

情況 1:"\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

情況 2:"\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

關鍵差異點

驗證代碼

#include <stdio.h>
#include <string.h>

int main() {
    char s1[] = "\La\016ef";
    char s2[] = "\La\018ef";
    
    printf("s1: sizeof=%zu, strlen=%zu\n", sizeof(s1), strlen(s1));
    printf("s2: sizeof=%zu, strlen=%zu\n", sizeof(s2), strlen(s2));
    
    // 打印十六制查看
    for (size_t i = 0; i < sizeof(s1); i++) printf("%02X ", (unsigned char)s1[i]); puts("");
    for (size_t i = 0; i < sizeof(s2); i++) printf("%02X ", (unsigned char)s2[i]); puts("");
    return 0;
}
/* 輸出示例:
s1: sizeof=6, strlen=5
s2: sizeof=7, strlen=6
4C 61 0E 65 66 00
4C 61 01 38 65 66 00
*/

最佳實踐:消除歧義

  1. 八進制轉義統一寫滿 3 位:\016 → \016 (已滿),\01 → \001
  2. 十六進制更安全:\x0E、\x01、\x38 ('8'),無貪婪匹配歧義
  3. 避免在字符串字面量中混用數字:"\x01" "8ef" 明確分隔
  4. 需求長度用 strlen:sizeof 含結束符,strlen 不含

總結

sizeof 計算數組總字節數 (含結束符),受編譯期字符串字面量解析影響。八進制轉義 \ddd 採用貪婪匹配:\016 為單字節 (0x0E);\018 解析為 \01 (0x01) + '8' (0x38) 兩字節,導致 sizeof 差 1。統一使用 \xHH 十六進制轉義 可徹底避免此類隱性 Bug。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
源碼片段解析結果字節數原因
\016八進制 016 (十進制 14)13 位合法八進制數字
\018八進制 01 (十進制 1) + 字符 '8'28 非八進制,貪婪匹配停止