再看下数组对应的代码:
- #include <iostream>
- using namespace std;
- void main()
- {
- int arr[2][3] = {1,2,3,4,5,6};
- int (*p)[3] = arr;
- }
分析二维数组int arr[2][3],它在内存中是顺序存储,分别按照行列来存贮,从arr下拉的可以看出,arr直接的有两个元素,分别是arr[0],arr[1],可以看出其类型是 int[3],这是一个数组,那么arr[0],arr[1]就代表着两个数组,表示的数组的首元素地址。
至于arr = arr[0] = &arr[0][0] = arr +0,以及arr + 1 =arr[1] 这些都还好理解。关键是 &arr[1] = arr[1] =*(arr + 1),这个该怎么理解呢。arr[1] 表示数组arr的首地址加上一个偏移量所指向的值,即*(arr + 1),所以*(arr + 1) = arr[1] = arr +1,这就是数组中指针的感觉有点奇怪的地方吧。其实本来就是这样,我们还可以这样理解,数组中的元素是按顺序存储的,那么arr + 1表示的第1(0,1)个元素的地址。*(arr + 1)表示的第1个元素的值,因为第一个元素是数组,那么数组的值使用首元素的地址表示的,那么对其进行解引用操作,结果肯定就是arr+ 1自身表示的地址了。或许有人感到奇怪,为什么*(arr + 1)代表的不是(arr+1)处的即第一行首元素的地址呢。我是这么思考的,arr + 1 所指的类型是int[],所以其解析成地址,而arr[1][0]的地址虽然是和arr + 1相同,但是两者表示的类型的不同。
我们知道&只是个取地址符号,如果针对一个一维数组来说,&a[i]表示的是第i个元素的地址,这个毫无疑问,但是针对多维数组呢?在数组 arr[2][3]中,arr[1]表示的第一个元素的地址,也可以说是表示第1行数组,&arr[1]表示的是什么东西呢,这个问题的本质其实就是数组名,对数组名取地址两者的区别。看下面的程序
- #include <iostream>
- using namespace std;
- void main()
- {
- intbrr[3] = {1,3,5};
- cout<<"brr的大小:"<<sizeof(brr)<<endl;
- cout<<"&brr的大小:"<<sizeof(&brr)<<endl;
- cout<<"brr's address is:"<<brr<<endl;
- cout<<"&brr'saddress is:"<<&brr<<endl;
- cout<<"brr+ 1's address is :"<<(brr + 1)<<endl;
- cout<<"&brr+1's address is :"<<(&brr + 1)<<endl;
- }
再看结果:
我们发现,brr表示的地址和&brr表示的地址两者相同,但是对两者进行+1操作的话,会发现,brr只是加了4个字节,但&brr却是加了4X3个字节(整个数组的大小)。到现在应该明白了两者的区别了吧,brr数组名表示地址,但是只等同于&brr[0],即,&brr表示的是整个数组的地址,两者虽然数值一样,但是类型不一样。
其实这里涉及到了一个隐式转换的问题。对于C++中的数组,除了在sizeof(array),&array外,数组名array都会被自动转换成&array[0].