雖然許多場合可互換(如 a[i] ≡ *(a+i)),但本質完全不同:
| 特性 | 陣列 | 指標 |
|---|---|---|
| 儲存位置 | 靜態區(全域)或堆疊(區域) | 指向任意記憶體(堆疊、堆、靜態、記憶體映射) |
| 位址/容量 | 生命週期內固定不變 | 可隨時修改指向 |
| 內容修改 | 可修改元素 | 可修改指向內容(若非指向常數) |
| sizeof | 整個陣列位元組數 | 指標變數本身大小(4/8 位元組) |
| 賦值/比較 | 不可直接整體賦值/比較 | 可直接賦值/比較位址 |
char a[] = "hello"; // 陣列在堆疊,內容可改 a[0] = 'X'; // OK char *p = "world"; // p 指向唯讀資料段(常數字串) p[0] = 'X'; // 編譯通過,執行期崩潰(Segmentation Fault)
規則:字串常值型別為 const char[],指向其的指標應宣告為 const char*。
char a[] = "hello"; char b[10]; // 錯誤:b = a; // 陣列名非可修改左值 // 錯誤:if (b == a) // 比較的是位址,非內容 strcpy(b, a); // 正確複製 if (strcmp(b, a) == 0) // 正確比較 // 指標操作 char *p = malloc(strlen(a)+1); strcpy(p, a); // 複製內容 if (strcmp(p, a) == 0) // 比較內容 free(p);
char a[] = "hello world"; // 含 '\0' 共 12 位元組
char *p = a;
printf("%zu\n", sizeof(a)); // 12
printf("%zu\n", sizeof(p)); // 4 (32-bit) 或 8 (64-bit)
// 函數參數傳遞:陣列退化為指標
void Func(char a[100]) {
printf("%zu\n", sizeof(a)); // 4/8,非 100!
}
鐵律:陣列作為函數參數時,自動退化為同類型指標,失去長度資訊。解決:傳遞長度參數、使用結構體封裝、或 C++ 使用 std::array/std::vector。
#define CONST_STR "const str" // 預處理器直接替換 // 1. 陣列:擁有獨立記憶體,內容可改 char arr1[100] = CONST_STR; // 複製到陣列 char arr2[100] = "literal"; // 複製到陣列 // 2. 指向常數字串:不可修改內容 const char *p1 = CONST_STR; // 指向唯讀區 const char *p2 = "literal"; // 同上 // 3. 指向動態記憶體:可修改內容 char *p3 = malloc(100); strcpy(p3, CONST_STR); // 複製內容,可修改 p3[0] = 'X'; // 4. 常數指標:指標本身不可改 char *const p4 = arr1; // p4 永遠指向 arr1,但可改內容
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CONST_STR "const str"
void test_array_strcpy_string() {
char a[100];
strcpy(a, "literal");
a[0] = 'A'; // OK
printf("array strcpy string: %s\n", a);
}
void test_pointer_string() {
char *p = "literal"; // 指向常數
// p[0] = 'A'; // Crash!
printf("pointer string: %s\n", p);
}
void test_pointer_strcpy_string() {
char *p = malloc(100);
strcpy(p, "literal");
p[0] = 'A'; // OK
printf("pointer strcpy string: %s\n", p);
free(p);
}
int main() {
test_array_strcpy_string();
test_pointer_string();
test_pointer_strcpy_string();
return 0;
}
const:const char *p = "...",編譯器會攔截修改嘗試。char a[] = "..." 或 malloc+strcpy。strcpy/memcpy,比較用 strcmp/memcmp。NULL、明確擁有權(誰 free)。深刻理解陣列與指標的記憶體模型差異,是寫出高效、無 Bug C/C++ 程式碼的基石。