1. 关于地址
// 三行五列
int a[3][5] = {{1, 2, 3, 4, 5},
{11, 21, 31, 41, 51},
{12, 22, 32, 42, 52}};
/*以下地址相同*/
// 整个数组的地址
printf("------------------------%d\n", &a);
// 第一行的首地址
printf("------------------------%d\n", a);
// 第一行第一个元素的首地址
printf("------------------------%d\n", *a);
2. 关于长度
// 三行五列
int a[3][5] = {{1, 2, 3, 4, 5},
{11, 21, 31, 41, 51},
{12, 22, 32, 42, 52}};
printf("------------------------%d\n", a);
// 相差 20 个字节 &a = 3 * 5 * 4 a = 5 * 4 *a = 4
printf("------------------------%d\n", a + 1);
3. 关于长度
// 三行五列
int a[3][5] = {{1, 2, 3, 4, 5},
{11, 21, 31, 41, 51},
{12, 22, 32, 42, 52}};
// 3 * 5 * 4 = 60 个字节
printf("------------------------%d\n", sizeof(*&a));
// 4 * 5 每行有五个数 实际取的是 a 的字节
printf("------------------------%d\n", sizeof(*a));
// 4 实际取的是 *a 的字节
printf("------------------------%d\n", sizeof(**a));
4. 关于取值
int a[3][5] = {{1, 2, 3, 4, 5},
{11, 21, 31, 41, 51},
{12, 22, 32, 42, 52}};
// 下标法取值 从 0 开始计算
printf("------------------------%d\n", a[2][3]);
指针法取值
还是以上述三行五列的数组为数据来源,该如何命名指针呢
int (*p)[5] = a;
没错,你没看错,它是以列数为数组的大小,为什么不是 3 呢?原因很简单,还记得 a 的字节数是多大吧,对,就是 5 * 4,那么对 p + 1 不就是 a + 1 嘛,所以 p + 1 就指向了下一行。那如何取值呢
// 取值 11
printf("-----------11111-------------%d\n", **(p + 1));
// 取值 42
printf("-------------11111-----------%d\n", *(*(p + 2) + 3));
为什么是两个 * 呢,不应该是一个 * 吗?其实想想也能明白了,*p 是整个二维数组的地址,也就是 &a,那么 *p 得到的就是 *a 的地址,也就是第一行首个元素的地址,那么 **p 就是解析首个元素的地址,得到值,想想上边的长度计算就能明白了。