二维数组
下面的代码先定义了一个整数二维数组,board[3][3]
int board[3][3]={
{'1','2','3'},
{'4','5','6'},
{'7','8','9'}
};
printf("*board:%9d\n",*board);//相当于board[0]
printf("board:%9d\n",board);//二维数组名也就是二维数组的首地址
printf("&board[0][0]:%9d\n",&board[0][0]);//第一个元素的地址
printf("board[0]:%9d\n",board[0]);//二维数组board的第一个子数组的名称/地址
printf("&board[0]:%9d\n",&board[0]);//相当于board
下面是运行的结果:
从运行结果和程序的注释可以看出,输出的值是一样的,但是表示的意思不大一样。
在解释之前,我们先回顾下一维数组的知识,int a[3]={1,2,3};
其中a是数组名,也是第一个元素a[0]的地址,
即a、&a、&a[0]三个的值一样的。(但是&a和a分别自加所移动的长度是不一样的)。 另外,*(a+1)就是a[1]就是数值2。
这应该是没有疑问的。好的,那进行下一步了。
下面简单了解下二维数组的组成(引用的是《c语言入门经典》的图):
从图中可以看出,board作为二维数组是由两层构成的,第一层为纵向数组,第二层为横向数组。
也就是说board是纵向数组的首地址,也就是纵向数组的第一个元素board[0]的地址。这就解释了board的值为什么等于&board[0]的值。而(board+i)就是对数组的第i的元素进行访问,所以*board就是*(board+0),就是board[0]。
第二层每个子数组里面由包含了各自的横向的一维数组,所以从这个角度上来说,board[0]这时候就成了数组名了,它包含了board[0][0]、board[0][1]、board[0][2]这三个元素。所以数组名board[0]就是数组的第一个元素board[0][0]的地址,即&board[0][0]。即board[0]与&board[0][0]的值是一样的。
又因为上面第一层的解释中我们已经知道了board[0]的值与board、*board、&board[0]相等。所以说上面程序中的五条输出语句的结果是一样的。
好了,说了那么多。不知道听晕了没有。总之,二维数组是由两层构成的。
其本质是因为二维数组在内存里面是连续存储的,即board[0][0]
一直到board[2][2]这九个数都是一个个紧挨着的。牢记这句话,这与一维指针数组是不一样的。
一维指针数组
先定义一个一维字符指针数组,
char *a[3]={"monday","tuesday","wednesday"};
printf("&a[][]:%d\n",&a[0][0]);
printf("a[0][0]:%c\n",a[0][0]);
printf("&a[0]:%d\n",&a[0]);
printf("a:%d\n",a);
printf("&a:%d\n",&a);
printf("a[0]:%d\n",a[0]);
下面是输出
可以看出a和&a、&a[0]结果一样,但是&a[0][0]与其他不一样。这与二维数组是不同的。正如我们之前所见的,二维数组的输出都是一样的。
首先我们要理解char a[3]的含义,这是定义了一个一维数组,数组名为a, 共有三个元素,且元素的类型是char *型。那么我们很清楚了,a是一维数组的名字,也是数组的首地址,所以与&a相等,也与数组的第一个元素的地址&a[0]一样。而a[0]是一个char型的指针变量,指针变量里面存放的是地址。而我们知道的通常情况下指针如int *p=&a,p和&p的内容是不一样的,p放的是要访问的变量a的地址,而&p是指针p的自己的内存地址,两者不一样。所以类似的,&a[0]与a[0]不是同一个东西。a[0]放的是“monday”这个字符串的地址,也就是’m’的地址,所以&a[0][0]即m的地址与a[0]是一样的,都为4216712。
至此,该解释的也说的差不多了。这就是两者的区别之处,希望大家多多注意。不对的地方欢迎提出来哈。