雖然均可用 a[i] / *(p+i) 訪問,但本質完全不同:
int n = 4;
int arr[n] = {1,2,3,4}; // 錯誤:n 非常量(C99 VLA 除外)
// 正確方式
#define N 10
int arr[N] = {0}; // 預處理階段 N→10
const int m = 5; // C++ 中可作數組長度,C 中為只讀變量
// int arr2[m]; // C 標準下非法
int a[5];
sizeof(a) // 20 (32位系統,5*4)
sizeof(a[0]) // 4
sizeof(a[5]) // 4 - 不會越界!sizeof 編譯期求值,不訪問內存
sizeof(arr):得到整個數組大小&arr:得到數組指針(類型 int(*)[5]),而非首元素地址int b[2][3]; // 2 行 3 列
// 內存佈局:連續 6 個 int
// b[0][0], b[0][1], b[0][2], b[1][0], b[1][1], b[1][2]

a++、--a、a = ... 皆非法&a[0](首元素地址)a vs &a 經典面試題int a[5] = {1,2,3,4,5};
int *ptr = (int*)(&a + 1);
printf("%d %d", *(a+1), *(ptr-1)); // 輸出:2 5
解析:
&a 類型 int(*)[5],&a+1 跳過整個數組(+20 字節)int* 後,ptr-1 回退 4 字節 → 指向 a[4] = 5ptr-1 回退 20 字節 → 指向 a[0] = 1*(int*)0x0018FF44 = 20; // 必須強轉,否則視為整數無法解引用
int *p = (int*)0x0018FF44; // 假設 p 自己的地址就是 0x0018FF44
*p = NULL; // 修改 p 指向的內存,即修改 p 自身 → p 變為 NULL
| 表達式 | 左值含義 | 右值含義 |
|---|---|---|
&ch | 非法 | ch 的地址 |
cp | cp 所代表的內存 | cp 的值(地址) |
&cp | 非法 | 指針變量 cp 的地址 |
*cp | cp 指向的內存 | cp 指向內存的內容 |
*cp+1 | 非法 | 內容+1 |
*(cp+1) | cp+1 指向的內存 | cp+1 指向內存的內容 |
++cp | 非法 | cp+1 指向的內容 |
cp++ | 非法 | cp 的原值 |
*++cp | cp+1 指向的內存 | cp+1 指向內存的內容 |
*cp++ | cp 指向的內存 | cp 指向內存的內容 |
++*cp | 非法 | 內容+1 |
(*cp)++ | 非法 | 內容(後++) |
優先級:++ > * > +
int arr[10];
int n = &arr[10] - &arr[0]; // 10 - 元素個數
// &arr[10] 合法(只取地址不訪問),&arr[-1] 非法(棧無預留空間)
int *arr[5]; // 5 個 int* 元素的數組
// 類型:int*[5]
// main 參數:char *argv[] 即指針數組

int (*p)[5]; // 指向含 5 個 int 的數組的指針
// 類型:int(*)[5]
// 二維數組退化:int a[2][3] → int(*)[3]

void fun(int arr[2][3]); // OK
void fun(int arr[][3]); // OK - 第二維必須給定
void fun(int (*arr)[3]); // OK - 等價寫法
// void fun(int arr[][]); // 錯誤
// void fun(int **arr); // 錯誤!二維數組 ≠ 二級指針
| 定義 | 聲明 | 結果 |
|---|---|---|
int arr[] = "abc"; | extern char *arr; | 崩潰:指針讀取字符串內容作地址 |
char *p = "abc"; | extern char str[]; | 亂碼:數組名讀取指針值作字符 |
// 定義指針,聲明數組時:
printf("%s", *(char**)str); // 或 (char*)*(int*)str
int a[5][5];
int (*p)[4] = (int(*)[4])a;
printf("%d %p", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
解析:
%d:指針相減得元素個數 = 4%p:-4 的無符號十六進制 = FFFFFFFCint a[4] = {1,2,3,4};
int *ptr1 = (int*)(&a + 1); // 跳過整個數組
int *ptr2 = (int*)((int)a + 1); // 地址+1 字節
printf("%x %x", ptr1[-1], *ptr2); // 輸出:4 20000000 (小端模式)

sizeof(arr) vs sizeof(ptr)int a[] 實為 int *a