分享
 
 
 

第三章 数组的解剖学

王朝other·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

这一章我们来讨论一下数组的内涵,对数组的内部构造进行一次解剖,看看里面究竟隐藏了什么秘密。 有了前面两章对数组名和C语言数组本质的澄清,再来理解这一章的内容,就容易多了。

在下面的叙述中,笔者会用到一个运算符sizeof,由于在不同的编译器和编译模式下,对一个地址进行sizeof运算的结果有可能是不同的,为了方便讨论,我都假设地址长度为4个字节。

多数教材在讲述数组的时候,都是把重点放在外部表现形式上,很少涉及数组的内部,只告诉你如何做,却忽视了为什么要这样做。在解释的过程中,还会列出各种各样的表达式,例如:a、a+1、a[0]、a[0][0]、&a[0]、&a[0][0]、*(a+1)等等,让人眼花缭乱。但实际上真正能够用来描述数组内部构造的表达式只有其中的几个。

上一章讲到,C语言的数组实现并非真正的多维数组,而是数组嵌套,访问某个元素的时候,需要逐层向下解析。仍然以上一章的例子数组int a[7][8][9]来说,第一维元素0的值a[0]是a[0]所代表的那个数组的首地址,这个表达式在C语言的数组里面具有特殊的意义,之所以特殊,不仅仅在于它所代表的东西与一般的地址不同,而且类型也并非一般的地址类型,它的类型叫做数组类型,数组类型这个名称在绝大多数教材中是从来没有出现过的,在C89标准中,也仅仅出现在介绍数组定义的那一段。具有数组类型的地址跟一般类型地址的主要区别,在于长度不一样,对一个一般类型的地址进行sizeof运算,结果是4个字节,而a[0]由于代表了一个数组,sizeof(a[0])的结果是整个数组的长度8x9xsizeof(int),并非4个字节。具有数组类型的地址跟数组名一样都是一个符号地址常量,因此它必定是一个右值。数组类型在数组的定义与引用中具有非常重要的作用,它可以用来识别一个标识符或表达式是否真正的数组,一个真正数组的数组名,是一个具有数组类型的符号地址常量,它的长度,是整个数组的长度,并非一般地址的长度,如果一个标识符不具备数组类型,那它就不是一个真正的数组。在后面的章节里,还会再次使用这个概念。

与a[0]类似的数组类型地址还有a[0][0],a[0][0]是a[0]的下一层数组,因此sizeof(a[0][0])的结果是9xsizeof(int)。类似地,对于一个三维数组:

a[i][j][k]

a、a[x]、a[x][y](其中x、y大于等于0而小于i、j)都是具有数组类型的地址常量,而且都是一个右值。这一点要牢牢记住。正是由这些特殊类型的地址构成了整个数组。

以上结论对于n维数组同样适用。

接下来跟各位一起讨论一下跟数组有关的各种表达式的意义及其类型:

&a[0][0][0]:

&a[0][0][0]仅仅是一个地址,它的意义,仅仅表示元素a[0][0][0]的地址,sizeof(&a[0][0][0])的结果是4。不少人把它说成是数组a的首地址,这是错误的,这是对数组首地址概念的滥用。真正能代表数组a的数组首地址只有a本身,a与&a[0][0][0]的意义根本就是两回事,真正的数组首地址是具有数组类型的地址,sizeof(a)结果是ixjxkxsizeof(int),而不是4,只不过由于a[0][0][0]位置特殊,恰好是数组a的第一个元素,所以它们的地址值才相同。而对于a[0]和a[0][0],它们是在数组a内部a[0]和a[0][0]所代表的那个数组的首地址,它们的地址值也是由于位置“特殊”,因此才跟a和&a[0][0][0]一样。这一点一定要区分清楚了。

a+i:

可能有些人会对a+i感到迷惑,数组的首地址加上一个整数是什么呢?它是第一维元素i的地址,sizeof(a+i)为4。

a[i]+j:

跟上面的类似,a[i]+j是a[i]所代表的那个数组的元素j的地址,sizeof(a[i]+j)的结果也为4。

&a:

对数组名取地址在C标准里面是未定义的。这个表达式曾经引起过争论,焦点在于对一个右值取地址的合法性。C89规定&运算符的操作数必须具有具体的内存空间,换言之就是一个左值,但数组名却是一个右值,按照&运算符的要求,这是非法行为。因此,早期的编译器通常规定&a是非法的。但不知道什么原因,现在的编译器都把&a人为地定义成一个比a高一级而地址值跟a一样的地址,但作为比a高一级的地址,有一个行为却非常怪诞,sizeof(&a)的结果跟sizeof(a)相同,这也是人为的痕迹。笔者倾向于把&a定义为非法,应该维护&运算符的权威性,而不是在规定对某个右值取地址为非法的同时,又允许对另一个右值取地址,这是互相矛盾的。

&a[i]和&a[i][j]:

跟&a一样,也是未定义的,同样不符合&运算符的规则。由于a[i]是a[i][j]的上一层数组,有些人可能会想当然地以为:a[i]=&a[i][j],错也,实际上,由于a[i][j]=*(a[i]+j),因此&a[i][j]=&*(a[i]+j),结果是a[i]+j。对于sizeof(&a[i])和sizeof(&a[i][j]),由于是未定义的,因此有些编译器规定其值跟sizeof(a[i])和sizeof(a[i][j])相同,有些编译器却规定为4,就是一个地址的长度。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有