遞歸實現 strlen 時,兩個關鍵錯誤:遞歸終止條件判斷指針本身而非指向字符,以及 scanf 讀取字符串時錯誤使用 &s。
int leng(char *s) {
if (s) // 錯誤:判斷指針是否為 NULL,而非字符是否為 '\0'
return leng(s+1) + 1;
return 0;
}
void main() {
char s[100];
scanf("%s", &s); // 錯誤:&s 是 char(*)[100] 類型,不匹配 %s 期望的 char*
int l = leng(s);
printf("%d", l);
}
if (s) 檢查指針 s 是否非空。字符串結束標誌是 '\0'(即 *s == 0),而非指針變為 NULL。傳入 s+1 只會移動指針,永遠不會變成 NULL,導致無限遞歸訪問越界內存直到崩潰。s 是數組名,本身已表示首元素地址(類型 char*)。&s 類型是 char(*)[100](指向整個數組的指針),雖然數值相同但類型不同,嚴格編譯器會警告,且語義不正確。#include <stdio.h>
int leng(char *s) {
if (*s) // 正確:判斷當前字符是否非 '\0'
return leng(s + 1) + 1;
return 0;
}
int main() {
char s[100];
scanf("%s", s); // 正確:直接用數組名 s
int l = leng(s);
printf("%d\n", l);
return 0;
}
leng("abc"):*'a' != 0 → leng("bc") + 1leng("bc"):*'b' != 0 → leng("c") + 1leng("c"):*'c' != 0 → leng("") + 1leng(""):*'\0' == 0 → 返回 0遞歸版本雖簡潔但有棧溢出風險(極長字符串)。尾遞歸優化需編譯器支援,通用做法用迴圈:
int strlen_iter(const char *s) {
int len = 0;
while (*s++) len++;
return len;
}
strlen 的實現技巧現代 libc 多用字對齊 + SIMD 指令一次檢測多字節,極大提升性能,遠快於逐字節循環。