sizeof 與 strlen 是 C 語言中最易混淆、最高頻考察的知識點。本質上:sizeof 是編譯期運算符,求類型/表達式佔用字節數;strlen 是運行期庫函數,計算以 '\0' 結尾的字串長度。 本文從本質、用法、陷阱、實戰五個維度徹底釐清。
| 維度 | sizeof | strlen |
|---|---|---|
| 性質 | 單目運算符(關鍵字) | 標準庫函數 (<string.h>) |
| 計算時機 | 編譯期(常量表達式) | 運行期(遍歷記憶體) |
| 參數類型 | 類型、變量、表達式、函數調用 | 僅 const char*(字串指針) |
| 結果含義 | 佔用存儲空間(字節數,含 '\0') | 字串有效字符數(不含 '\0') |
| 括號要求 | 類型必加括號;變量/表達式可選 | 必須加括號(函數調用) |
| 對數組名 | 整個數組大小 | 退化為指針,計算字串長度 |
sizeof(int) // 4 (典型 32/64 位系統)
sizeof(double) // 8
sizeof(char) // 1 (標準保證)
int a = 10;
sizeof(a) // 4,不讀取 a 的值
sizeof(a + 1.5) // 8,表達式類型為 double,不計算 a+1.5
sizeof(func()) // func 返回類型大小,func() **不會被調用**
int arr[10];
sizeof(arr) // 40 (10 * 4),數組大小
int *p = arr;
sizeof(p) // 8 (64位指針大小),指針本身大小
sizeof(*p) // 4,指向的 int 大小
函數參數退化:
void foo(int arr[10]) { // 實際為 int* arr
sizeof(arr); // 8 (指針大小),非 40!
}
struct S { char c; int i; }; // 因對齊通常佔 8 字節
sizeof(struct S) // 8,含填充字節
sizeof(func) ❌(但 sizeof(func()) ✅)sizeof(void)、sizeof(外部聲明未定義的結構體)sizeof(s.bitfield) ❌
size_t strlen(const char *s) {
size_t len = 0;
while (*s++) len++;
return len;
}
依賴 '\0' 結束符,遇到第一個 '\0' 停止。
char a[] = {'h', 'e', 'l', 'l', 'o'}; // 無 '\0'
strlen(a); // 未定義行為:繼續讀取直到隨機遇到 '\0',結果不可預測
char b[] = "hello"; // 編譯器自動補 '\0',等價於 {'h','e','l','l','o','\0'}
strlen(b); // 5,正確
char *p = "hello";
strlen(p); // 5
sizeof(p); // 8 (指針大小)
char arr[] = "hello";
strlen(arr); // 5
sizeof(arr); // 6 (含 '\0')
#include <stdio.h>
#include <string.h>
struct { char c; int i; } s = {'a', 10};
char str[] = "Hello";
char *p = str;
printf("sizeof(s) = %zu\n", sizeof(s)); // 8 (對齊)
printf("sizeof(str) = %zu\n", sizeof(str)); // 6 (含 \0)
printf("strlen(str) = %zu\n", strlen(str)); // 5
printf("sizeof(p) = %zu\n", sizeof(p)); // 8 (指針)
printf("strlen(p) = %zu\n", strlen(p)); // 5
sizeof(arr) = 整個數組大小;strlen(arr) = 字串長度(若無 '\0' 會崩潰)。sizeof(ptr) = 指針大小(4/8);strlen(ptr) = 字串長度。牢記本質區別,臨場不再混淆。