(1)二维数组的初始化:
请参见博客 http://blog.youkuaiyun.com/chenshijun0101/article/details/6640377/
在此博客中用到了static,当二维数组定义到代码域内(即二维数组是局部变量)并且声明为static,而且显式 初始化 为非0,则在编译的时候,会将此二维数组放到数据段内。
当二维数组定义到代码域内(即二维数组是局部变量)并且声明为static,而且初始化 为0或者没有显式初始化,则在编译的时候,会将此二维数组放到BSS段内,放在 BSS段内,编译器会自动将其全都赋值为0。
(2)一维数组各个符号的含义:(在总结二维数组之前首先复习一维数组各个符号的含义)
假设先定义:int a[10];
a: a作右值时,代表数组首元素的首地址,而非数组的首地址,虽然两者的数值是一样的(等同于&a[0])
(数组的首地址需要数组指针int (*)[10]来表示)。
a不能用作左值,a作左值时代表数组整体, C语言规定数组操作时要独立单个操作(例如只能a[0]之类的访 问),不能整体操作数组。但是*(a+1)这种表示是能做左值的,此时左值表示的是首元素的 首地址,还有另外一种情况我认为也作左值:sizeof(a),运行结果是sizeof(a)
= 40,从结果 是40可以看出sizeof中的a代表了整个数组,和a是左值的含义相同,因此我认为此处a应该作 的是左值。除了这两种情况,其他情况a都不能作为左值。(sizeof是关键字,在编译时候计算出 来结果)
a本身是int *p类型的
&a: &a作右值时代表整个数组的地址,其类型是int (*)[10];
&a不能作为左值,(&a实质是一个常量,不是变量因此不能赋值,所以自然不能做左值。)
&a[0]: &a[0] 作右值时代表首元素的首地址(和a的含义完全相同)。
&a[0]不能作为左值。
&a[0]本身是int *p类型的
(3)二维数组各个符号的含义:
char a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
测试a[0]的含义:
sizeof(a[0]) = 4;
char *p = a[0];没有报警告,说明类型匹配,另外也说明a[0]做右值的时候代表地址
printf("a[0] = %p\r\n",a[0]); 结果是a[0]的值 = 0x804a014
printf("a[0]+1 = %p\r\n",a[0]+1); 结果是a[0]+1的值= 0x804a015
综合前面四句代码可以看出来,a[0]所表现出来的特性和一维数据时候的a所代表的含义完全相同。
据此可以推测出,二维数组其实是三个一维数组组成的。每一个一维数组名字是a[i],
a[i]作右值的时候代表第i个一维数组首元素的首地址(等价于&a[i][0])。
a[i]的匹配类型是char *p
进一步验证:
printf("&a[0] = %p\r\n",&a[0]); 结果是&a[0] = 0x804a014
printf("&a[0]+1 = %p\r\n",&a[0]+1); 结果是&a[0]+1 = 0x804a018
从上面两句代码可以看出&a[0]代表组成二维数组的三个一维数组中第一个一维数组的首地址
与(2)讲解的一维数据相对比,二维数组中的&a[0]和一维数组中的&a是一样的。
&a[0]的类型是char (*p)[4](指针数组)。
测试a、&a、&a[0]的含义:
sizeof(a) = 12; 说明a作左值的时候代表整个二维数组。
printf("&a[0] = %p\r\n",&a[0]); 结果是&a[0] = 0x804a018
printf("&a[0]+1 = %p\r\n",&a[0]+1);结果是&a[0]+1 = 0x804a01c
printf("a = %p\r\n",a); 结果是 a = 0x804a018
printf("a+1 = %p\r\n",a+1);结果是 a+1 = 0x804a01c
上面四句代码可以看出a作为右值的时候和&a[0]是等价的,
代表了二维数组中第一个一维数组的首地址(注意不是首元素的首地址)。
a的类型是char (*p)[4](指针数组)
printf("&a = %p\r\n",&a); 结果是&a = 0x804a018
printf("&a+1 = %p\r\n",&a+1);结果是&a+1 = 0x804a024
从上面两句代码可以看出来,&a代表整个二维数组的首地址。
(4)二维数组的使用:
见陈正冲编著的《C语言深度解剖第二版》第105、106页