對於二維數組 char cs[2][3],以下四種表達式指向同一地址(首元素 &cs[0][0]):
p1 = &cs[0][0];
p2 = &cs[0];
p3 = &cs;
p4 = cs; // 最常用
但它們的類型不同,影響指針運算步長:
cs 類型 char (*)[3],+1 跨過一行(3 個元素)。*cs 類型 char *,+1 移動一個元素。int nums[2][3] = {{11,12,13},{21,22,23}};
int *p1 = &nums[0][2]; // 直接取地址
int *p2 = nums; p2 += 2; // 利用首地址 + 偏移
// 兩者均指向 nums[0][2] (值 13)
for (int i=0; i<2; i++)
for (int j=0; j<3; j++)
printf("%d\n", nums[i][j]);
int *p = nums;
for (int i=0; i<6; i++)
printf("%d\n", *(p+i)); // 或 *p++
char cs[2][3] = {{'A','B','C'},{'D','E','F'}};
char *p = cs;
for (size_t i=0; i < sizeof cs / sizeof cs[0][0]; i++)
printf("%c\n", *p++);
for (int i=0; i<6; i++)
printf("%c\n", *(*cs + i)); // *cs 為首行首地址
char cs[2][3];
printf("%p, %p\n", cs, *cs); // cs: 數組地址, *cs: 首行地址 (同值)
printf("%c, %c\n", **cs, cs[0][0]); // **cs 解引用兩次得首元素值
char cs[2][2][3] = { {{'A','B','C'},{'D','E','F'}}, {{'1','2','3'},{'4','5','6'}} };
/* 方法 1:雙重解引用 + 偏移 */
for (int i=0; i < sizeof cs / sizeof cs[0][0][0]; i++)
printf("%c\n", *(**cs + i));
/* 方法 2:轉為一維指針(推薦,清晰) */
char *p = (char *)cs;
for (int i=0; i < sizeof cs / sizeof cs[0][0][0]; i++)
printf("%c\n", *p++);
| 表達式 | 類型 | 含義 | +1 步長 |
|---|---|---|---|
cs | char (*)[3] | 指向含 3 元素的數組指針 | 3 * sizeof(char) |
*cs | char * | 指向首元素 | sizeof(char) |
**cs | char | 首元素值 | N/A |
&cs | char (*)[2][3] | 指向整個二維數組 | 整個數組大小 |
void func(int arr[][3], int rows) 或 void func(int *arr, int rows, int cols) 配合一維索引 arr[i*cols + j]。