C语言深度解剖(精讲版)——读书笔记15 &&自己的一些理解
第四章 指针和数组
数组
一.数组的内存布局
先看下面的例子:
int a[5];
数组示意图:数组包含5个int类型的数据 |
如图我们定义一个数组a时,编译器根据指定的元素个数和元素类型分配确定大小的一块内存(大小为:元素类型大小*元素个数),并把这块内存的名字命名为a。名字a一旦与这块内存匹配就不能被改变。
现在来看一下下面问题:
sizeof(a)的值 sizeof( int )*5 ,32位系统下为20
sizeof(a[0])的值sizeof (int),32位系统下为4
sizeof (a[5])的值在32位系统下为4,并没有出错,为什么呢?
解析:关键字sizeof求值是在编译的时候,虽然并不存在a[5]这个元素,但是这里并没有去真正访问a[5],而是仅仅根据数组类型来确定其值。因此这里不会出错;
二.&a[0]和&a的区别
这里&a[0]和&a的区别到底有什么?a[0]是一个元素,a是整个数组,虽然&a[0]和&a值一样,但其值意义不一样。
&a[0] 表示:数组首元素的首地址; &a 表示:数组的首地址;
三.数组名a作为左值和右值的区别
x=y
左值:编译器认为x的含义是x代表地址,这个地址只有编译器才知道,编译在一个特定的区域保存这个地址,我们完全不必考虑这个地址保存在哪。
右值:编译器认为y的含义是y所代表的地址里面的内容,这个内容是什么,只有到运行时才知道。
a作为右值时意义:与&a[0]是一样的,代表的是数组首元素的首地址,而不是数组的首地址;【注意的是:这仅仅是代表,并没有一个地方来存存储这个地址,也就是说编译器并没有为数组a分配一块内存来存储其地址,这一点就与指针有很大差别】
a不能作为左值! 编译器会认为数组名作为左值代表的意思是a的首元素的首地址,但是这个地址开始的一块内存是一个总体,我们只能访问数组的某个元素,而无法把数组当一个总体进行访问。
所以我们可以把a[i]当左值,而无法把a当左值,其实我们完全可以把a当做一个普通的变量来看,只不过这个变量内部分为很多小块,只能通过分别访问这些小块来达到访问整个变量a的目的