C 語言動態內存分配後,scanf 直接使用指針讀取字符串是否合法?本文分析指針解引用與 scanf 格式匹配的關係,澄清常見誤解。
int main() {
char *a;
a = (char *)malloc(40); // 分配 40 字節
scanf("%s", *a); // 這裡 *a 是 char 類型,而非 char*
return 0;
}
*a 類型錯誤| 表達式 | 類型 | scanf("%s", ...) 期望類型 | 結果 |
|---|---|---|---|
a | char * | char * (緩衝區地址) | ✅ 正確 |
*a | char (首字符值) | char * | ❌ 類型不匹配,未定義行為 |
scanf("%s", a); // 直接傳指針 a (地址)
// 或
scanf("%s", &a[0]); // 等價,首元素地址
*a 取首字符值 (如 0),作為地址傳給 scanf → 寫入地址 0x0 → 段錯誤#include <stdio.h>
#include <stdlib.h>
int main() {
char *buffer = malloc(40);
if (!buffer) {
perror("malloc failed");
return 1;
}
// 限制輸入長度防止溢出 (留 1 字節給 '\0')
if (scanf("%39s", buffer) != 1) { // %39s 最多讀 39 個非空白字符
fprintf(stderr, "Input error\n");
} else {
printf("Read: %s\n", buffer);
}
free(buffer);
return 0;
}
malloc 返回 void*,轉型為 char* 即緩衝區起始地址scanf("%s", ptr) 要求 ptr 為 char*,指向可寫內存*ptr 解引用得到 char,不是地址,不可傳給 %smalloc 返回值,必限制輸入寬度 (如 %39s),必 free代碼 scanf("%s", *a) 不合法:*a 類型為 char,而 %s 需 char*。正確用法 scanf("%39s", a)。動態內存讀取字符串需「檢查分配、限制寬度、釋放內存」三部曲。