問題代碼
int slen(int *p) { // 參數類型錯誤
int l=0;
for(; *p!='\0'; p++) l++;
return l;
}
int main() {
char s[1000];
int *p = s; // char* 強制賦值給 int*,類型不匹配
gets(s); // 危險:無緩衝區溢出保護
printf("%d", slen(p));
}
核心錯誤分析
- 指針類型錯誤:
slen 參數為 int*,但傳入 char*。
在 32/64 位系統上 sizeof(int) != sizeof(char),指針算術 p++ 會按 sizeof(int) (4/8 字節) 遞增,導致每次跳過 3/7 個字符,讀取到的值非預期字符,最終讀到垃圾內存中的 0 終止,長度計算完全錯誤(常見輸出 256 等隨機值)。 - 使用 `gets()`:C11 已移除,無長度檢查,極易造成緩衝區溢出漏洞,嚴禁使用。
- 無需指針變量:直接傳遞數組名
s(退化為 char*)即可。
正確寫法
#include <stdio.h>
#include <string.h> // 標準庫 strlen
// 方式 1:使用標準庫(推薦)
int main() {
char s[1000];
printf("請輸入字符串:");
fgets(s, sizeof(s), stdin); // 安全讀取,含換行符
s[strcspn(s, "\n")] = '\0'; // 移除換行
printf("長度:%zu\n", strlen(s));
return 0;
}
// 方式 2:手寫教學版(正確指針類型)
size_t my_strlen(const char *p) {
size_t len = 0;
while (*p++) len++;
return len;
}
建議
- 生產代碼直接用
strlen / strnlen。 - 輸入永遠用
fgets / getline / scanf("%999s", s) 限制長度。 - 指針類型必須與指向對象類型嚴格匹配,開啟編譯器警告(
-Wall -Wextra / /W4)可自動捕獲此類錯誤。