原本觉得本身对二维数组的理解还能够,没感受有什么,可是今天小伙伴问了一个问题感受迷惑了很久,因而决定细致的记录一下,一步一步的探究各类关于二维数组的问题,巩固基础。shell
首先定义二维数组数组
int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
而后开始研究二维数组名和地址的关系spa
// 打印a a[0] 和 a[0][0]的地址 cout << "the value of a: " << a << endl; cout << "the value of a[0]: " << a[0] << endl; cout << "the address of a[0][0]: " << &a[0][0] << endl;
the value of a: 0x7ffe5b8c1ee0 the value of a[0]: 0x7ffe5b8c1ee0 the address of a[0][0]: 0x7ffe5b8c1ee0
就如各类资料说的那样,能够看出三个表达指向的是一个地址,继续看指针
这里看一下每一行\(a[i], 0\leq i<3\)code
for (int i = 0; i < 3; ++i) cout << "the value of a[" << i << "]" << " is " << a[i] << endl;
the value of a[0]is 0x7ffe5b8c1ee0 the value of a[1]is 0x7ffe5b8c1eec the value of a[2]is 0x7ffe5b8c1ef8
打印的结果是每一行的首地址,能够看出来每两个地址之间差12个字节,也就是三个int的长度(每一个int是四个字节,大部分编译器是这样的)。这与咱们预期的是同样的,毕竟是每行的首地址。索引
继续走,咱们看到\(a, a[0], a[0][0]\)的地址是同样的,都是最头上的首地址,那么这里用这个地址推导进而显示其余位置的元素编译器
// 由a[0]推出其余,这里以第1行第1列(0 base)为例 cout << "the address of a[0+1]+1 " << "is " << a[0+1]+1 << endl; cout << "the value of a[0+1]+1 " << "is " << *(a[0+1]+1) << endl; cout << "the address of a[0]+4 " << "is " << a[0]+4 << endl; cout << "the value of a[0]+4 " << "is " << *(a[0]+4) << endl;
the address of a[0+1]+1 is 0x7ffe5b8c1ef0 the value of a[0+1]+1 is 5 the address of a[0]+4 is 0x7ffe5b8c1ef0 the value of a[0]+4 is 5
前两种行是经过加a[0]的索引获得其余行的首地址,而后再加偏移量获得的,后两行是直接计算偏移量获得的。博客
继续,由\(a[0][0]\)的地址推导编译
// 由&a[0][0]推出其余, 这里以第1行第1列(0 base)为例 cout << "the address of a[0][0]+4 " << "is " << &a[0][0]+4 << endl; cout << "the value of a[0][0]+1 " << "is " << *(&a[0][0]+4) << endl;
the address of a[0][0]+4 is 0x7ffe5b8c1ef0 the value of a[0][0]+1 is 5
这里和上面的第二中直接加偏移量的状况是同样的。class
如今是让人有点迷惑的地方,就是数组名a既然和\(a[0], a[0][0]\)指向的地址同样,那么是否用法也同样呢?
咱们先来看看如何用a获得\(a[1][1]\)
// 假设要求a[1][1](5) cout << "a[1][1] inferred from a : " << *(*(a+1)+1) << endl;
a[1][1] inferred from a : 5
a+1指向的是\(a[1]\),这里是第1行(0 base)的首地址,对它解引用获得a[1]的地址,而后+1就获得\(a[1][1]\)的地址了。
前面说a+1是指向地址的,那么是否是意味a是一个二级指针呢?
int *p = a; // 不经过
实验发现报错,说明a不是一个指针类型,继续看
int *p = *a; cout << "the value of p is: " << p << endl; cout << "the value of *p is: " << *p << endl; cout << "the value of p+1 is: " << p+1 << endl; cout << "the value of *(p+1) is: " << *(p+1) << endl; cout << "a[1][1] inferred from p : " << *(p+1*3+1) << endl;
the value of p is: 0x7ffe5b8c1ee0 the value of *p is: 1 the value of p+1 is: 0x7ffe5b8c1ee4 the value of *(p+1) is: 2 a[1][1] inferred from p : 5
对a解引用后确实是一个地址,因此能够定义指针,而且能够用加偏移量的方式获得\(a[1][1]\)
更为有趣的是
cout << "a[1][1] inferred from p[] : " << p[1*3+1] << endl;
a[1][1] inferred from p[] : 5
指针p表现的居然像一个一维数组(由于直接按索引就能够获得元素),这里也增长了一种新的取元素方式。这可能和[]的工做方式有关,这部分仍是没弄明白,欢迎指导。
这篇博客详细的记录了由二维数组名引出的各类细节,虽然还不完善,可是确实让本身巩固了基础,之后估计应该不会倒在二维数组了……吧。