數組名是首元素地址常量,數組指針變量可指向數組或數組元素,支援算術運算。
int a[5] = {1,2,3,4,5};
int *pa = a; // pa 指向 a[0]
// 等價關係:
// pa == a == &a[0]
// pa+1 == a+1 == &a[1]
// *(pa+i) == a[i]
a[i],直觀、編譯器自動計算偏移。*(pa+i) 或 pa[i],本質相同,指針算術顯式化。
// 方式 1:指針遞增
int *pa = a;
for (int i = 0; i < 5; ++i) {
printf("%d ", *pa++);
}
// 方式 2:指針與下標混用
for (int i = 0; i < 5; ++i) {
printf("%d ", pa[i]);
}
// 方式 3:範圍 for (C99 VLA 或 C++)
int *end = a + 5;
for (int *p = a; p < end; ++p) {
printf("%d ", *p);
}
數組作參數退化為指針,實際傳遞首元素地址。形參可寫 int *pa 或 int pa[] 或 int pa[5](長度被忽略)。
float average(float *scores, int n) {
float sum = 0;
for (int i = 0; i < n; ++i) sum += scores[i]; // 或 *scores++
return sum / n;
}
int main() {
float s[5] = {80, 90, 85, 95, 70};
printf("Avg: %.2f\n", average(s, 5)); // s 退化為 float*
}
二維數組 int a[3][4] 在內存中按行主序連續存儲。關鍵類型:
a 類型:int (*)[4](指向含 4 個 int 的數組的指針)。a[0] / *a 類型:int[4],退化為 int* 指向 a[0][0]。&a[0][0] 類型:int*。a+1 指向第 2 行,偏移 4*sizeof(int) 字節。| 表達式 | 類型 | 值(假設 a 基址 1000,int 4 字節) |
|---|---|---|
a | int (*)[4] | 1000 |
a[0] | int* (退化) | 1000 |
*a | int* (退化) | 1000 |
&a[0][0] | int* | 1000 |
a+1 | int (*)[4] | 1016 |
a[1] | int* | 1016 |
*(a+1) | int* | 1016 |
&a[1][0] | int* | 1016 |
// a[i][j] 等價形式:
*(a[i] + j) // a[i] 退化為行首指針
*(*(a + i) + j) // a+i 指向第 i 行,解引用得行首指針
// 統一公式:*(*(a + i) + j)
int a[3][4] = {...};
int (*p)[4] = a; // p 指向整個二維數組(實為指向首行)
// p+1 指向第 2 行
// *(p+i)+j 是 a[i][j] 地址
// *(*(p+i)+j) 是 a[i][j] 值
int (*p)[4]。int *p[4] 是指針數組(4 個 int*),完全不同。
int a[3][4] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};
int (*p)[4] = a;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++j) {
printf("%2d ", *(*(p+i)+j));
}
printf("\n");
}
char *ps = "C Language"; // ps 指向只讀字符串字面量區
// 等價
char *ps; ps = "C Language";
// 指針算術:跳過前 10 字符
ps += 10; // 指向 'g'
printf("%s\n", ps); // 輸出 "guage"
ps[0] = 'x' → UB)。char buf[] = "C Language"; 或 malloc。
void my_strcpy(char *dst, const char *src) {
while ((*dst++ = *src++) != '\0');
// 或精簡:while (*dst++ = *src++);
}
int main() {
char *src = "CHINA";
char dst[10];
my_strcpy(dst, src);
printf("%s\n", dst); // CHINA
}
const char *src 保護源字符串不被修改。*dst++ = *src++ 結合賦值、遞增、判斷,極度精簡。int (*p)[N] 攜帶列數信息,編譯器自動計算行偏移。int *p[N] 是指針數組,int (*p)[N] 是數組指針,括號決定一切。const 正確表達意圖。for(p=begin; p 是 C 風格標準範式。