size_t strlen(const char *s); // 函式,執行期計算
size_t sizeof(expression); // 運算符,編譯期計算(大多數情況)
| 特性 | strlen | sizeof |
|---|---|---|
| 性質 | 庫函式 | 運算符(關鍵字) |
| 計算時機 | 執行期 | 編譯期(靜態陣列/型別)或執行期(VLA) |
| 參數 | char*,必須以 \0 結尾 | 型別或變數/運算式 |
| 語意 | 字串實際長度(不含 \0) | 物件佔用位元組數 |
| 陣列退化 | 陣列名退化為指標 | 陣列名不退化,保留完整大小 |
| 動態記憶體 | 可用 | 只能得指標大小,無法得分配大小 |
char str[20] = "0123456789";
int a = strlen(str); // 10
int b = sizeof(str); // 20
char *ss = "0123456789";
sizeof(ss); // 4/8 (指標大小)
sizeof(*ss); // 1 (char)
strlen(ss); // 10
char ss2[] = "0123456789";
sizeof(ss2); // 11 (含 \0)
strlen(ss2); // 10
char ss3[100] = "0123456789";
sizeof(ss3); // 100
strlen(ss3); // 10
int arr[100];
sizeof(arr); // 400 (100 * sizeof(int))
// strlen(arr) // 編譯錯誤:參數型別不符
void fun(char buf[8]) // 等價於 void fun(char *buf)
void fun(char buf[]) // 等價於 void fun(char *buf)
void fun(char *buf) {
sizeof(buf); // 4/8 (指標大小),非陣列大小!
}
解決方案:額外傳遞長度參數,或在函式內用 memcpy 複製到本地陣列。
struct X { int i; int j; char k; }; // 通常 12 bytes (對齊填充)
struct X x;
sizeof(X); // 12
sizeof(x); // 12
sizeof(&x); // 4/8 (指標)
// 1. 陣列索引
size_t my_strlen1(const char *s) {
size_t i = 0;
while (s[i] != '\0') i++;
return i;
}
// 2. 指標遞增
size_t my_strlen2(const char *s) {
size_t len = 0;
while (*s++) len++;
return len;
}
// 3. 指標相減
size_t my_strlen3(const char *s) {
const char *p = s;
while (*p++);
return p - s - 1;
}
// 4. 遞迴
size_t my_strlen4(const char *s) {
return *s ? 1 + my_strlen4(s + 1) : 0;
}
// 5. 標準庫風格 (Linux kernel)
size_t my_strlen5(const char *s) {
const char *sc;
for (sc = s; *sc != '\0'; ++sc);
return sc - s;
}
strlen。sizeof。\0)→ 必須用 sizeof 或顯式長度,不可用 strlen。{ void *data; size_t len; }。