首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言 sizeof 與 strlen 徹底解析:編譯期 vs 運行期

     編輯:關於C語言

核心區別一覽

特性sizeofstrlen
性質運算符(編譯期計算)庫函數(運行期計算)
參數類型或表達式(不求值)const char*(必須以 \0 結尾)
返回類型/對象佔用位元組數(含結構填充)字串有效字符數(不含 \0)
陣列退化不退化(保留完整類型)退化為指標
動態記憶體只能得指標大小正常計算字串長度

經典案例對照表


char str1[] = "abc";        // char[4]  {'a','b','c','\0'}
char str2[] = {'a','b','c'}; // char[3]  無 \0
char str3[5] = "abc";       // char[5]  {'a','b','c','\0','\0'}
char *p = "abcde";          // char* → 唯讀區 "abcde\0"

sizeof(str1) = 4;   strlen(str1) = 3
sizeof(str2) = 3;   strlen(str2) = 隨機值(無 \0,UB)
sizeof(str3) = 5;   strlen(str3) = 3
sizeof(p)    = 8;   strlen(p)    = 5   // 64位系統指標8字節

深度原理解析

1. sizeof 編譯期計算

  • 對陣列:sizeof(arr) = 元素數 × sizeof(元素類型)。
  • 對指標:sizeof(ptr) = 指標本身大小(4/8 字節)。
  • 表達式不求值:int a=1; sizeof(a=2); → sizeof(int),a 仍為 1。
  • 函數調用:sizeof(f()) → sizeof(返回類型),f() 不會真調用。

2. strlen 運行期掃描

  • 從指標開始逐字節檢查直到遇到 \0。
  • 若陣列無 \0(如 char a[3]={'a','b','c'};),讀越界 → 未定義行為。
  • 只接受 char*,不能直接傳 int* 或結構體。

3. 字串字面量的特殊性


char *p = "hello";      // p 指向 .rodata 區,不可修改
char a[] = "hello";     // 編譯器把字面量複製到棧陣列 a,可修改
// 等價於
const char *p = "hello";
char a[] = {'h','e','l','l','o','\0'};

實戰陷阱

  1. 函數參數退化:void f(char s[100]) 實為 char* s,函數內 sizeof(s) 只得指標大小。
  2. 結構體填充:struct {char c; int i;} → sizeof=8(非 5),對齊導致。
  3. 多維陣列:int a[3][4]; sizeof(a)=48,但傳參退化成 int(*)[4]。

最佳實踐

  • 需要「容器大小」用 sizeof;需要「字串長度」用 strlen。
  • 自定義陣列長度宏:#define ARR_LEN(arr) (sizeof(arr)/sizeof((arr)[0])) —— 僅適用於陣列變數,不可用於指標。
  • 動態字串結構體:struct Str { size_t len; char *data; } 避免重複 strlen。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved