(一)数组的内存布局

对于语句int a[5]; 我们明白这里定义了一个数组,数组里有5个元素,每一个元素都是int类型,我们可以用a[0],a[1]等访问数组里的元素,但是这些元素的名字就是a[0],a[1]吗?

请看下面的内存布局图:

如上图所示,当我们定义一个数组int a[5],编译器根据指定的数组元素以及数组元素类型分配内存,分配内存的大小是:元素类型大小*元素个数,并且把这个空间命名为a,a[0],a[1]是数组a的元素,但不是数组元素的名字,数组的每一个元素是没有名字的。

我们再来看看sizeof关键字的几个问题:

sizeof(a)的值是sizeof(int)*5,32位系统下是20;

sizeof(a[0])的值是sizeof(int),32位系统下是4;

sizeof(&a[0])的值在32位系统下为4,这很好理解,取首元素a[0]的首地址;

sizeof(&a)的值也是4,取数组a的首地址。

程序:

 #include <stdio.h>

 void main()
{
int a[] = {, , , , };
printf("sizeof(a):%d\n", sizeof(a));
printf("sizeof(a[0]):%d\n", sizeof(a[]));
printf("sizeof(&a[0]):%d\n", sizeof(&a[]));
printf("sizeof(&a):%d\n", sizeof(&a));
}

程序输出:

 sizeof(a):
sizeof(a[]):
sizeof(&a[]):
sizeof(&a):

(二)省政府和市政府的区别-&a和&a[0]

我们首先在程序中把&a和&a[0]的值打印出来:

 #include <stdio.h>

 void main()
{
int a[] = {, , , , };
printf("&a:%d, &a[0]:%d\n", &a, &a[]);
}

其结果是: &a:, &a[]:

我们发现这两者的值是一样的,那么这两者有什么区别呢?a是整个数组,而a[0]是数组首元素,因此&a是整个数组首地址,&a[0]是数组首元素地址,举个例子更好理解:湖南的省政府在长沙,而长沙的市政府也在长沙,二者地址一样,但代表的意义却完全不同。

(三)数组名a作为左值和右值的区别

先来理解下左值和右值:

简而言之,出现在赋值符号“=”左边的就是左值,而右边则是右值,

比如x=y;

左值:在这个上下文环境中,编译器认为x的含义是x所代表的地址,这个地址只有编译器知道,在编译的时候确定,编译器在一个特定的区域保存这个地址,我们完全不必考虑这个地址保存在哪里;

右值:在这个上下文环境中,编译器认为y的韩式是y所代表的地址里面的内容。这个内容是什么,只有到运行时才知道。

既然明白了左值和右值的区别,下面就讨论下数组作为左值和右值的区别:

当a 作为右值的时候代表的是什么意思呢?很多书认为是数组的首地址,其实这是非常错误的。a 作为右值时其意义与&a[0]是一样,代表的是数组首元素的首地址,而不是数组的首地址。这是两码事。但是注意,这仅仅是代表,并没有一个地方(这只是简单的这么认为,其具体实现细节不作过多讨论)来存储这个地址,也就是说编译器并没有为数组a分配一块内存来存其地址,这一点就与指针有很大的差别。

a 作为右值,我们清楚了其含义,那作为左值呢?
a 不能作为左值!这个错误几乎每一个学生都犯过。编译器会认为数组名作为左值代表的意思是a 的首元素的首地址,但是这个地址开始的一块内存是一个总体,我们只能访问数组的某个元素而无法把数组当一个总体进行访问。所以我们可以把a[i]当左值,而无法把a当左值。其实我们完全可以把a 当一个普通的变量来看,只不过这个变量内部分为很多小块,我们只能通过分别访问这些小块来达到访问整个变量a 的目的。

(四)a和&a的区别

对于数组int a[5];若我们要定义指针变量接受a,我们可以这样做 int *pa = a; 但是我们若要定义指针接受&a,使用int *pa = &a却不行,编译器报错a value of type "int(*)[5]" cannot be assigned to an entity of type "int *",从这个报错我们知道&a的类型是int(*)[5],这是一个指向数组指针,数组里有5个元素。

为了看到a,&a的区别,

我们将a和&a的值打印出来: printf("a:%d, &a:%d\n", a, &a); ,并将a+1和&a+1打印: printf("a+1:%d, &a+1:%d\n", a+, &a+);

其结果是:

 a:, &a:
a+:, &a+:

从上面两行的打印我们可以看出,数组名a里存放的是数组首元素的地址,而&a是整个数组的地址,这两者在值上是一样的,但是a和&a 做+1操作时,a+1增加的是一个元素的大小4,而&a+1增加的是整个数组的大小20。

最新文章

  1. 《你不知道的JavaScript》整理(四)——原型
  2. A Simple OpenCASCADE Qt Demo-occQt
  3. UVA11324 The Largest Clique[强连通分量 缩点 DP]
  4. 使用Myeclipse插件将wsdl生成java客户端代码
  5. link2001错误无法解析外部符号metaObject
  6. 用 Freemarker 生成 word 文档(包含图片)
  7. Android中Intent组件详解
  8. 【Java 基础篇】【第三课】表达式、控制结构
  9. python中时间和时区
  10. Eclipse 插件 —— SVN 的下载与安装
  11. Windows下Postgre SQL数据库通过Slony-I 实现数据库双机同步备份
  12. Mysql group_concat
  13. DOM重绘对focus的影响
  14. CSS3的翻转效果
  15. 转载 C语言中volatile关键字的作用
  16. mysql测试
  17. PHP 常用header头定义
  18. Windows server 2008R2远程桌面3389端口修改方法技巧
  19. EBS WebADI 存储过程增加参数
  20. 关于 web 页面 占满全屏

热门文章

  1. python 输入一个整数,判断其是否既是3的倍数,又是5的倍数
  2. 安装psutil时提示缺少python.h头文件(作记录)
  3. 跨浏览器实现placeholder效果的jQuery插件
  4. 路由(二) router-link的使用
  5. jquery--DOM操作基础
  6. ZYNQ的Linux Linaro系统镜像制作SD卡启动
  7. Python学习笔记:第3天 字符串的操作
  8. 爬虫-scrapy五大核心组件及工作流
  9. 安装cuda9.0+cudnn v7+python3.5.3+tensorflow
  10. OracleLinux上安装数据库(DBCA)