如何理解int**指向二位数组
1.什么是二维数组
相关链接:二维数组
理解二维数组就要理解二维数组是如何在内存中存储的,二维数组是在内存中按行优先原则进行连续存储的。那什么叫行优先原则呢,就拿一个四行三列的arr数组来说,在内存中首先存储a[0][0]
,第二个元素存储a[0][1]
就是行优先,第二个元素存储a[1][0]
就是列优先。所以,在内存中首先存储完第一行的元素,而后再存储第二行、第三行的元素,因此,arr[i][j]
中的i是行号,j是列号。图为二维数组arr
的元素及行地址,其中二维数组标识符arr
表示arr[0][0]
的地址,arr[0]
、arr[1]
表示arr[0][0]
和arr[1][0]
地址。
从数据类型上来看,一个存储整型数据的一维数组的标识符是一个指向整型数组的指针。
二维数组本质上是一系列一维数组的集合,而指针的集合在C语言中的表示为指针数组,那么二维数组本质上可以看作是一个指针数组,所以二维数组的标识符就可以看作是一个指向指针数组的指针。
2.什么是int**
int *p
在C语言中表示一个指向整型的指针。
int **p
在C语言中则表示一个指向整型指针的指针。
3.int**如何指向二维数组
arr[0][0]
也可以看作是取一个一维数组的第0个元素,只是此时的一维数组变成了arr[0]
,而不是一维数组中的字母标识符。
如前文所述,二维数组本质上是一维数组的集合,二维数组的标识符则是指向指针数组的指针,也可以看作是指向指针的指针,如果其中存储的数据为整型,则二维数组的标识符就可以看作是int**
类型。
而此时如果进行下述输入
int arr[3][3] = {{0},{1},{2},{3}};
int **p = arr;
就会出现如下错误
warning: initialization from incompatible pointer type [enabled by default]
警告给指针变量赋值时的类型不匹配。
这说明在系统内部并不认为arr
为int**
类型
那么这时,该如何进行表示呢?
看如下代码:
运行的结果是:
address a:0xbfe06ae8
address *p:0xbfe06ae8
address p:0xbfe06adc
address b:0xbfe06adc
address *b:0xbfe06ae8
value **b:1
address a[0]:0xbfe06ae8
address p[0]:0xbfe06ae8
address b[0]:0xbfe06ae8
value a[0][0]:1
value b[0][0]:1
value (*b)[0]:1
由上述实验,可以得出如下结论:
1.p
和b
的地址相同,都是指向二维数组首元素的指针的地址,也就是文中所定义的指向指针数组的指针的地址。
2.*b、*p、a、a[0]、p[0]、b[0]
地址相同,都是二维数组首元素的地址,b和p都是文中定义的指针数组,指针数组的标识符所存储的值就是首元素的地址。
3.**b
:实际上就是取*b
的值,即a[0][0]
的值。
4.a[0][0]、b[0][0]、(*b)[0]
:实际上都是二维数组首元素的值。而b是一个int**
类型,这就成功用一个int**
类型表示了一个二维数组,并实现了访问二维数组的值。
综上,使得int**
成为一个指向指针数组的指针,就可以用其表示二维数组。