| 代碼 | 存儲區域 | 類型 | sizeof 結果 | 可修改性 |
|---|---|---|---|---|
char str[] = "abc"; | 棧(局部) / 數據段(全局) | char[4] | 4 | ✅ 可修改 |
char* ptr = "abc"; | 指針在棧,字符串在常量區 | char* | 4/8(指針大小) | ❌ 修改導致崩潰 |
char str2[10] = "abc"; | 棧/數據段 | char[10] | 10 | ✅ 可修改 |
void func(char sa[100]) | 參數退化為 char* | char* | 4/8 | 視實際指向而定 |
"abc" 編譯器自動補 \0 存為 "abc\0"。是否為常量取決於上下文:
char str[] = "abc")→ 編譯器視為元素列表 {'a','b','c','\0'},在棧/數據段分配數組空間,非常量,可修改。char* ptr = "abc")→ 編譯器將字面量放入只讀常量區,ptr 指向該地址。雖類型非 const char*,但寫入觸發段錯誤。建議寫法:const char* ptr = "abc",編譯期捕獲錯誤。char[3] ≠ char[4]。sizeof 作用於類型:sizeof(str) = 數組總字節數;sizeof("abc") = 4(含 \0)。void f(char a[100]) 等價 void f(char* a),sizeof(a) 為指針大小。char str[] = "abcdef"; // sizeof=7
char* ptr = "abcdef"; // sizeof=4/8
char str2[10] = "abcdef"; // sizeof=10
void func(char sa[100]) { // sizeof(sa)=4/8
printf("%zu\n", sizeof(sa));
}
strlen 計算 \0 前字符數,不含結束符。sizeof 編譯期常量,strlen 運行期遍歷。char* p = "hello"; p[0] = 'H'; → 段錯誤const char* p = "hello"; 或 char p[] = "hello";void f(char a[10]) { sizeof(a); } 以為得 10 → 實得 4/8sizeof 與 strlen字符串字面量存儲位置由定義方式決定:數組初始化 → 棧/數據段可寫;指針指向 → 常量區只讀。sizeof 看類型,數組不退化時得全長,退化為指針得指針大小。牢記這兩點,規避 90% 指針字符串 Bug。本文整理自 51CTO 技術博客筆記。