sizeof 是編譯期運算符,計算類型/對象佔用的存儲字節數;strlen 是運行期庫函數,計算字符串的可見字符長度 (不含 '\0')。
| 特性 | sizeof | strlen |
|---|---|---|
| 性質 | 運算符 (關鍵字) | 庫函數 (<string.h>) |
| 計算時機 | **編譯期** (常量表達式) | **運行期** (遍歷內存) |
| 參數 | 類型名 (需括號) / 表達式 (可無括號) | const char* (以 '\0' 結尾的字符串) |
| 返回值 | 佔用字節數 (size_t) | 字符個數 (size_t),不含結束符 |
| 適用對象 | 任意類型/變量/表達式 | 僅 C 風格字符串 |
| 數組參數 | 退化為指針時**只能得指針大小** | 正常工作 (接收指針) |
#include
#include
void func(char arr[]) { // 參數退化為 char*
printf("sizeof(arr) in func = %zu\n", sizeof(arr)); // 4/8 (指針大小)
}
int main() {
int *p = NULL;
int a[10] = {0};
char b[] = "hello"; // 包含結束符,長度 6
printf("sizeof(p) = %zu\n", sizeof(p)); // 4/8 (指針大小)
printf("sizeof(*p) = %zu\n", sizeof(*p)); // sizeof(int) = 4
printf("strlen(b) = %zu\n", strlen(b)); // 5 (不含 '\0')
func(b); // sizeof(arr) = 4/8
printf("sizeof(a) = %zu\n", sizeof(a)); // 40 (10 * 4)
printf("sizeof(b) = %zu\n", sizeof(b)); // 6 (含 '\0')
return 0;
}
sizeof(*p) 等價於 sizeof(指向類型)。"hello" 是長度 6 的 const char[6],sizeof("hello") == 6。struct A {
char c; // 偏移 0, 大小 1
// 填充 3 字節 (對齊 int 4 字節)
int i; // 偏移 4, 大小 4
// 結構體大小目前 8,最大成員 4,8 是 4 的倍數 → 無尾部填充
}; // sizeof(A) = 8
struct B {
int i; // 偏移 0, 大小 4
char c; // 偏移 4, 大小 1
// 尾部填充 3 字節 → 整體 8 (4 的倍數)
}; // sizeof(B) = 8
struct C {
char c1; // 0
char c2; // 1
short s; // 2 (short 對齊 2)
int i; // 4 (int 對齊 4)
}; // sizeof(C) = 8
// 數組在結構體中按元素逐個對齊,非整體
struct D {
char c;
int arr[2]; // c偏移0, 填充3, arr[0]偏移4, arr[1]偏移8
}; // sizeof(D) = 12
union U {
int i; // 4
char c[10]; // 10
double d; // 8
}; // sizeof(U) = 16 (max=10, 對齊 max_align_t 通常 8/16 → 16)
#pragma pack(1) // 1 字節對齊 (無填充)
struct Packed { char c; int i; }; // sizeof = 5
#pragma pack() // 恢復默認對齊
**慎用**:可能導致非對齊訪問性能下降或硬件異常 (ARM Cortex-M 等)。
sizeof(int)、sizeof(struct A)。sizeof a、sizeof a + b (等價 sizeof(a) + b)。sizeof(a)、sizeof(int),避免歧義,增強可讀性。strlen 用於非 '\0' 結尾內存 → 野指針越界讀取,崩潰/數據洩露。sizeof 計算元素個數 → 得指針大小。**必須額外傳長度**。sizeof(ptr) 以為是指向內存大小 → 實為指針自身大小。strlen,緩衝區容量用 sizeof(buf) (僅定義處)。sizeof(*ptr) 獲取真實大小。offsetof (stddef.h) 計算成員偏移,配合靜態斷言驗證佈局。| 場景 | 正確用法 | 錯誤示例 |
|---|---|---|
| 字符串可見長度 | strlen(str) | sizeof(str) (若 str 是指針/參數) |
| 緩衝區字節容量 | sizeof(buf) (定義處) | strlen(buf) (未初始化/含 '\0' 中間) |
| 結構體實例大小 | sizeof(obj) | 手動加和成員大小 |
| 指向類型大小 | sizeof(*ptr) | sizeof(ptr) |
| 函數參數數組長度 | 額外參數傳 len | sizeof(arr) 在函數內 |
搞清 sizeof (編譯期存儲大小) 與 strlen (運行期字符長度) 的本質區別,掌握指針退化、結構體對齊、聯合體共享內存規則,是 C 語言內存管理與接口設計的核心基本功。