本文主要解释这个问题,如下代码中,打印出来的值a+1和*(a+1)是一样的。
#include <stdio.h>
void main()
{
int a[2][3]={
1, 3, 5,
7, 9, 11
};
printf("%d\n", a);//整个数组的首地址
printf("%d\n", *a);//数组第一行元素的首地址
printf("%d\n", a+1);//a指向的下一个元素的首地址
printf("%d\n", *(a+1));//数组第二行元素的首地址
printf("%d\n", *(*(a+1)));//这一行只是为了验证确实是7这个值
}
上面代码中,数组a是一个二维数组,为什么 a+1 和 *(a+1)会是一样的呢?这两个都是指针,它们的首地址相同,但是它们的类型不同。 a+1的类型为 int (*)[3],*(a+1)的类型为int *。
先来看 a + 1:
a 表示这个这个二维数组的首地址, a的类型为 int (*)[3],这是一个指针,指向一个一维数组 int[3]。a + 1呢? 就会在原来地址的基础上+sizeof(int[3])。而sizeof(int[3])=12。所以a+1比a多12。
而*(a+1)的类型,是在 a+1的类型 int (*)[3]的基础上,进行一次解析,少一个*,即类型为 int[3],而这个类型当成指针来处理,就是int*了。
这里有一个重要的地方,那就是 a+1 这个指针,实际并不占用内存,上面的代码,只有整个数组占用一块内存。
数组名是一个常量,在编译时就已经赋值,不会额外开辟存储空间。
在汇编语言中就是,这叫直接寻址(即其空间中存放的就是值本身),而指针是变量,叫间接寻址(即空间中存放的是地址,通过这个地址再访问其指向的值)。
a+1这个地址,是由a计算出来的,而a这个符号常量并不占内存。所以对*(a+1),也就不存在解析这个指针里面的内容。这个解析,解析的是 指针的类型,由int (*)[3]类型解析成了int[3]类型。