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

C++ sizeof 運算子與 strlen 函式的完整差異解析

     編輯:C++ 入門

前言

在 C/C++ 程式設計中,sizeof 與 strlen 是兩個極易混淆卻又截然不同的工具。前者是編譯期運算子,後者是執行期函式;前者計算「類型或變數佔用的記憶體位元組數」,後者計算「C 風格字串的可見字元長度」。本文將從定義、評估時機、參數類型、回傳值語意、典型陷阱與最佳實踐六個維度,為您徹底釐清兩者的差異。

核心差異速查表

特性sizeofstrlen
性質編譯期運算子(關鍵字)執行期函式(/)
參數型別名稱 或 表達式(不評估副作用)const char*(以 null 結尾的字串指標)
回傳型別size_t(無號整數)size_t
計算內容物件/型別佔用的位元組總數(含 padding)字串中第一個 '\0' 前的字元數(不含結尾 null)
陣列退化不退化,能正確取得整個陣列大小退化為指標,只能取得指標大小
動態記憶體回傳指標變數本身大小(4/8 位元組)正確計算字串長度(前提是合法 C 字串)

深度解析

1. sizeof:靜態的大小守門員

int arr[10];
printf("%zu\n", sizeof(arr));        // 40 (10 * sizeof(int))
printf("%zu\n", sizeof(int));        // 4
printf("%zu\n", sizeof(arr + 0));    // 8 (指標大小,陣列退化)

struct Align { char c; int i; };     // 因對齊通常佔 8 位元組
printf("%zu\n", sizeof(Align));      // 8
  • 不評估表達式:sizeof(func()) 不會呼叫 func(),僅根據回傳型別計算大小。
  • 型別安全:可直接用於型別名稱 sizeof(double)。
  • 結構體對齊:包含 padding,sizeof(struct) ≥ 成員大小總和。

2. strlen:動態的字串量尺

char str[] = "Hello";
printf("%zu\n", strlen(str));        // 5
printf("%zu\n", sizeof(str));        // 6 (含結尾 '\0')

char *p = malloc(100);
strcpy(p, "World");
printf("%zu\n", strlen(p));          // 5
printf("%zu\n", sizeof(p));          // 8 (64-bit 指標大小)
  • 必須以 null 結尾:若記憶體中無 '\0',行為未定義(可能崩潰或讀取垃圾資料)。
  • 僅適用 char*:不可用於 wchar_t*、std::string 或非字串緩衝區。
  • O(n) 時間複雜度:每次呼叫都會掃描字串。

經典陷阱與避坑指南

陷阱 1:函式參數中的陣列退化

void bad_print_size(int arr[]) {
    // 這裡 arr 實際是 int*,sizeof 回傳指標大小
    printf("Size in func: %zu\n", sizeof(arr)); // 8 (64-bit)
}

int main() {
    int a[10];
    printf("Size in main: %zu\n", sizeof(a));   // 40
    bad_print_size(a);
}

解法:改用模板傳遞陣列參考 template<size_t N> void f(int (&)[N]),或額外傳遞長度參數,或改用 std::vector/std::array。

陷阱 2:結構體大小 ≠ 成員大小總和

struct Foo { char c; double d; }; // 通常 16 位元組 (1+7 padding+8)
printf("%zu\n", sizeof(Foo));       // 16,而非 9

使用 #pragma pack 或屬性 __attribute__((packed)) 可壓縮結構體,但可能影響存取效能或觸發對齊錯誤(視架構而定)。

陷阱 3:strlen 用於非字串緩衝區

int data[5] = {1,2,3,4,5};
// 錯誤!data 不是以 '\0' 結尾的字串
// size_t len = strlen((char*)data); // 未定義行為

現代 C++ 最佳實踐

  1. 優先使用標準容器:std::string、std::vector、std::array 內建 .size(),型別安全且不退化。
  2. 需要編譯期大小:用 sizeof 搭配 static_assert 驗證佈局。
  3. 需要執行期字串長度:用 std::string::length() 或 std::strlen(僅限 C 風格字串介接時)。
  4. 避免手動記憶體管理:new/malloc 易導致 sizeof 誤用,改用智慧指標與容器。

總結

sizeof 是編譯期的「靜態藍圖」,告訴你類型佔多少位元組;strlen 是執行期的「動態卷尺」,量測以 null 結尾的字串有多少可見字元。牢記「sizeof 看型別,strlen 看內容」,並善用現代 C++ 容器,即可徹底避開這對經典易混淆概念的坑。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved