指針與數組關係密切,下標操作均可用指針實現,且代碼更緊湊靈活。
int a[10], *p; p = &a[0]; // 等價 p = a; 數組名即首元素地址
等價關係:
p+i / a+i → &a[i](第 i 元素地址)*(p+i) / *(a+i) → a[i](第 i 元素值)p[i] 等價 *(p+i),下標可負:p=a+5; p[2]==a[7]; p[-3]==a[2]int a[3][4] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};
a:首地址(第 0 行首地址)a+1:第 1 行首地址(跨 4*sizeof(int) 字節)a[i] 即 *(a+i):第 i 行首地址(int*)a[i]+j 即 *(a+i)+j:第 i 行第 j 列元素地址*(*(a+i)+j) / (*(a+i))[j] 等價 a[i][j]注意:a 與 *a 數值相同(均為首地址),但類型不同:a 為 int(*)[4],*a 為 int*。
int (*p)[n]int a[3][4], (*p)[4]; p = a; // p 指向第 0 行 p+1; // 指向第 1 行,步長 4*sizeof(int) *(p+i)+j; // 指向 a[i][j]
與 int *p[4](指針數組)區別:括號改變結合優先級。
int a[3][4] = {{1,3,5,7},{9,11,13,15},{17,19,21,23}};
int i, (*b)[4];
b = a+1; // 指向第 1 行
for(i=1; i<=4; b=b[0]+2, i++) printf("%d\t", *b[0]); // 9 13 17 21
for(i=0; i<3; i++) { b=a+i; printf("%d\t", *(b[i]+1)); } // 3 11 19
\0,佔用長度+1 字節。char s[] = "a string"; 複製到棧上,可修改。char *cp = "a string"; 指向只讀區,cp[i] 訪問第 i 字符,不可修改。char *month_name(int n) {
static char *name[] = {"Illegal month","January",...,"December"};
return (n<1||n>12) ? name[0] : name[n];
}
main() { for(i=0;i<13;i++) printf("%s\n", month_name(i)); }
指針是重中之重,必須大量練習實戰題才能掌握。