编译器只给这20字节空间取了一个名字a,数组的每一个元素都没有名字。
数组大小:
数组在一片连续的内存空间中存储元素
数组元素的个数可以显示或隐式指定
int a[5] = {1,2}; //显示
数组大小sizeof(a) = 20, 数组长度 sizeof(a)/sizeof(*a) = 5 ,指定数组长度,不管初始化列表有多少个元素,都会以指定的长度来作为唯一的指标分配数组的内存空间
如果初始化列表元素个数小于指定的数组大小的时候,编译器会将剩下的元素以0来初始化,即a[2]=0,a[3]=0,a[4]=0
如果把数组初始化为全0,可以 int a[5] = {0};
int b[] = {1,2}; //隐式
此时数组长度又初始化列表中元素个数所决定,数组大小sizeof(b) = 8, 数组长度 sizeof(a)/sizeof(*a) = 2
数组地址与数组名
数组名代表数组首元素的地址
数组的地址需要用取地址符&才能得到
数组首元素的地址值与数组的地址值相同
数组首元素的地址与数组的地址是两个不同的概念
a是数组首元素的地址
&a是整个数组地址
数组名的盲点
数组名可以看做一个常量指针,但数组名其实并不是指针,在外部申明时不能混淆
数组名“指向”的是内存中数组首元素的起始位置
在表达式中数组名只能作为右值使用
只有在下列场合数组名不能看做常量指针
数组名作为sizeof操作符的参数
数组名作为&运算符的参数
因为C语言中,在一般情况下,数组名看做是一个常量指针,所以不可以出现在赋值符号的左边,所以不能a=b;这么用
数组名a作为左值和右值的区别
——一以下摘自 陈正冲《C语言深度剖析》
如x = y
左值:在这个上下文环境中,编译器认为x 的含义是x 所代表的地址。这个地址只有编译器知道,在编译的时候确定,编译器在一个特定的区域保存这个地址,我们完全不必考虑这个地址保存在哪里。
右值:在这个上下文环境中,编译器认为y 的含义是y 所代表的地址里面的内容。这个内容是什么,只有到运行时才知道。
C 语言引入一个术语----- “可修改的左值”。意思就是,出现在赋值符左边的符号所代表的地址上的内容一定是可以被修改的。换句话说,就是我们只能给非只读变量赋值。
数组作为左值和右值的情况:
当a 作为右值的时候代表的是什么意思呢?很多书认为是数组的首地址,其实这是非常错误的。a 作为右值时其意义与&a[0]是一样,代表的是数组首元素的首地址,而不是数组的首地址。这是两码事。但是注意,这仅仅是代表,并没有一个地方(这只是简单的这么认为,其具体实现细节不作过多讨论)来存储这个地址,也就是说编译器并没有为数组a分配一块内存来存其地址,这一点就与指针有很大的差别。
a 不能作为左值!这个错误几乎每一个学生都犯过。编译器会认为数组名作为左值代表的意思是a 的首元素的首地址,但是这个地址开始的一块内存是一个总体,我们只能访问数组的某个元素而无法把数组当一个总体进行访问。所以我们可以把a[i]当左值,而无法把a当左值。其实我们完全可以把a 当一个普通的变量来看,只不过这个变量内部分为很多小块,我们只能通过分别访问这些小块来达到访问整个变量a 的目的。