所谓"在表达式中,数组名总是被转换为指向该数组第一个元素的指针"应该如何理解?

在C语言中,数组名是一个左值,不是指针,之所以说“在表达式中,数组名总是被转换为指向该数组第一个元素的指针“是因为你可以使用用于操作指针的解引用符号"*"对数组名进行操作,或者你可以将一个数组名赋值给一个指针变量。

但实际上对数组名的操作和对指针的操作在汇编层是不同的。

数组int array[10]:

执行表达式 X = array[3]只需要两条汇编语句:

mov    -0x10(%ebp),%eax  /* -0x10(%ebp)是array[3]的内容 */

mov    %eax,-0x8(%ebp)   /* %ebp - 0x8 是X的地址 */

 

同样的操作,看指针是什么情况。

指针int *array_p = array;

执行表达式 X = array_p[3]会被编译器翻译成"X = *(array_p + 3);",看它的汇编代码:

mov    -0x4(%ebp),%eax /* %ebp - 0x4 是array_p的左值,它存放了数组array的第一个元素的地址

* 即array的值*/

add    $0xc,%eax   /* 将数组0元素地址+0xc得到第三个元素的地址 */

mov    (%eax),%eax   /* 取出这个值 */

mov    %eax,-0x8(%ebp) /* 将array[3]的(右)值存储到X中 */

 

对于指针而言,"[]"操作会被编译器翻译成"*( + )"操作,并且指令数是数组的二倍。

那么,对于数组而言,"[]"会不会被翻译成"*( + )"呢?

来看执行X = *(array + 3);执行这个表达式同样需要四条汇编语句:

lea    -0x1c(%ebp),%eax /* %ebp - 0x1c是array的左值,即数组0元素地址*/

add    $0xc,%eax /* 将这个地址+0xc得到第三个元素的地址 */

mov    (%eax),%eax /* 取出这个值 */

mov    %eax,-0x8(%ebp) /* 将array[3]的(右)值存储到X中 */

与指针不同,由于没有开辟存放数组名左值的空间,因此第一条语句直接使用"lea"指令计算array左值送入%eax;

与数组"[]"操作不同,它需要2倍于该操作的汇编语句。

由此可以得出结论:在表达式中,array[x]不会被翻译成*(array + x)!!

 

总结:

就本人而言"在表达式中,数组名总是被转换为指向该数组第一个元素的指针"这个C程序员的金科玉律始终不能被自己接受。在我的脑海里

,指针是“货真价实”的变量,它有自己的空间存储地址;而数组名则不一样,它更像是int i;因为数组名这个地址存储的是数组的0元素的内

容,但偏偏你又可以在不进行任何类型转换的情况下通过"pointer = array_name;"将它赋值给一个指针,这玩意儿简直太奇怪了!!不过硬

要让自己适应这个“异类”的话也不难,只需要记住这条汇编语句"lea    0xarray(%ebp),%eax",也就是:CPU直接将数组名放到寄存器里,

这就是它与众不同的原因了:-)

最后,我希望将标题修改一下使它看起来更加严谨——

在表达式中,数组名总是被转换为指向该数组第一个元素的“指针“。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值