對於`char *s[] = {"str1", "str2", "str3"};`這類字符指針數組,正確計算元素個數的方法是`sizeof(s) / sizeof(s[0])`或`sizeof(s) / sizeof(char*)`。本文解析原理並糾正常見錯誤。
char *s[] = {"key1=value1", "key2=value2", "key3=value3"};
// 假設64位系統,指針8字節
// s 在棧上連續存儲3個指針:
// s[0] → "key1=value1" (常量區)
// s[1] → "key2=value2"
// s[2] → "key3=value3"
| 表達式 | 值(64位) | 說明 |
|---|---|---|
| `sizeof(s)` | 24 (3 * 8) | **整個數組佔用的總字節數** |
| `sizeof(s[0])` | 8 | **單個元素(指針)大小** |
| `sizeof(char*)` | 8 | 等價於 `sizeof(s[0])` |
| `sizeof(s) / sizeof(s[0])` | **3** | ✅ **正確元素個數** |
| `sizeof(s) / sizeof(char*)` | **3** | ✅ 等價寫法 |
// 錯誤寫法
sizeof(s) / sizeof(**s) // **s 解引用兩次得到 char,大小為1
// 結果:24 / 1 = 24 (完全錯誤)
// 錯誤原因:
// s : char*[3] (數組類型)
// s[0] : char* (元素類型,指針)
// *s / s[0]: char* (首元素值,指針)
// **s : char (首字符,大小1字節)
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
// 使用
int count = ARRAY_SIZE(s); // 3,類型安全,編譯期計算
struct Item { int id; char *name; };
struct Item items[] = {{1, "A"}, {2, "B"}};
int n = ARRAY_SIZE(items); // 2
核心口訣:數組名sizeof得總大小,元素sizeof得單個大小,相除得個數;指針退化後sizeof失效,必須傳長度。