int main() {
char *key[2];
scanf("%s", &key[0]);
scanf("%s", &key[1]);
printf("%s\n", &key[0]);
return 0;
}
| 輸入 | 輸出 | 說明 |
|---|---|---|
whos who | whoswho | 第一字串 4 字元 + \0 正好 4 位元組 (32 位指標大小) |
wwwwww dddddd | wwwwdddddd | 6 字元超出 4 位元組,溢位覆蓋 |
char *key[2]; // 棧上分配 2 個指標 (32位系統各 4 bytes,共 8 bytes)
/*
記憶體圖示 (位址遞增向右):
key[0] (4 bytes) | key[1] (4 bytes)
指標值 指標值
*/
key[0] 與 key[1] 僅是兩個指標變數,各佔 4 位元組 (32 位系統),未分配任何字串儲存空間。
scanf("%s", &key[0]) 將字串寫入 key[0] 所在的 4 位元組空間key[1] 空間key[0] 的結束符 \0 被覆蓋,導致 printf 繼續讀取 key[1] 區域最後輸入的字串寫入 key[1],其後無其他變數被覆蓋,結束符保留,故能正確輸出。
char *key[2];
scanf("%s", &key[0]); // 寫入指標變數本身,非指向的記憶體
char key[2][100]; // 2 個 100 字元緩衝區
scanf("%99s", key[0]);
scanf("%99s", key[1]);
char *key[2];
key[0] = malloc(100);
key[1] = malloc(100);
scanf("%99s", key[0]);
scanf("%99s", key[1]);
// 使用後 free(key[0]); free(key[1]);
char buffer[200];
char *key[2] = {buffer, buffer + 100};
scanf("%99s", key[0]);
scanf("%99s", key[1]);
| 宣告 | 記憶體含義 | 可直接存字串? |
|---|---|---|
char *p; | 1 個指標 (4/8 bytes) | 否,需 malloc |
char p[100]; | 100 字元緩衝區 | 是 |
char *p[2]; | 2 個指標 (8/16 bytes) | 否,各需指向有效記憶體 |
char p[2][100]; | 2×100 字元緩衝區 | 是 |
現代編譯器 (GCC/Clang/MSVC) 對 scanf("%s", &key[0]) 會發出警告:
warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char **' [-Wformat=]
永遠不要忽略編譯器警告,這正是型別不匹配的鐵證。
char *key[N] 僅建立 N 個指標,不包含字串儲存空間。初學者常混淆「指標陣列」與「二維字元陣列」。牢記:指標需指向有效記憶體才能存取資料,否則必然導致未定義行為與難以診斷的 Bug。