| 維度 | sizeof | strlen |
|---|---|---|
| 性質 | 運算子 (關鍵字) | 函式 (<string.h>) |
| 計算時機 | 編譯期 (常數摺疊) | 執行期 |
| 參數類型 | 任意型別/變數/運算式 | const char* (以 \0 結尾) |
| 回傳值 | 型別/物件佔用 位元組數 (含結構對齊填充) | 字串 字元長度 (不含結束符 \0) |
| 陣列參數 | 不退化,得整個陣列大小 | 退化為指標,得指標大小 |
| 動態記憶體 | 得指標大小,無法得知分配大小 | 正常運作 (若以 \0 結尾) |
| 結果型別 | size_t (無號整數) | size_t |
char str[] = "hello"; // 陣列,大小 6 (含 \0)
char *p = "hello"; // 指標,指向常數區
sizeof(str); // 6 ✅
strlen(str); // 5 ✅
sizeof(p); // 4/8 (指標大小) ❌ 非字串長度
strlen(p); // 5 ✅
struct A { char c; int i; }; // 典型對齊:c(1) + padding(3) + i(4) = 8
sizeof(struct A); // 8 (含填充位元組)
#pragma pack(1)
struct B { char c; int i; };
#pragma pack()
sizeof(struct B); // 5 (無填充)
void Func(char arr[100]) {
sizeof(arr); // 4/8 (退化為 char*) ❌
}
void Func2(char *ptr) {
sizeof(ptr); // 4/8
}
// 解決:額外傳長度參數,或用結構體包裹陣列
extern int arr[]; // 不完整型別 (無大小)
sizeof(arr); // 編譯錯誤 ❌
sizeof 運算元若是型別名稱,必須加括號:sizeof(int)。變數名可不加:sizeof var。sizeof 不求值運算元:sizeof(i++) 不會讓 i 遞增。strlen 依賴 \0,若字串未正確結尾 → 越界讀取 → UB。std::string/std::vector 用 .size(),勿用 sizeof。sizeof 看型別,編譯期定乾坤;
strlen 數字元,執行期尋 \\0 根。
陣列不退化,sizeof 量全身;
指標退化殘,sizeof 只量尖。
動態記憶體,sizeof 盲無邊;
結構對齊隱,sizeof 知淵源。
sizeof 是靜態型別系統的鏡子,映照編譯期已知的位元組佔用;strlen 是執行期字串處理的尺子,量度以 \0 為界的字元長度。搞清「陣列退化」、「動態記憶體無長度」、「結構對齊」三大陷阱,方能精準用尺。