好多教科书都有这种说法,尽管“相当于”不是“就是”、“等于”,但很容易让学生产生概念混淆。
首先要搞清楚常数和常量:int a,const b;a=5//把常数5给a;a=b;//把常量b的值给a.
我认为:将“数组名”赋值给一个指针,这时的“数组名”不是常量,而是一个常数,常量和常数虽然共同点是不能更改,但有很大的区别。常量需要定义,在数据区开辟存储空间,而常数不需要定义,是和指令一起走的,从汇编的角度看,c编译器的&运算和宏定义都最后被编译器编译成一个常数和指令出现在代码区,也称为指令操作数(立即数)。
当然,要在c编译后的汇编指令里看常数和常量的区别,需要将数据定义为全局变量,这些变量在静态区,定义后地址确定。如果在函数内部定义,由于是定义在栈中,地址不确定,编译器对取地址运算不会送入常数,会是基于栈的基址做相对的变址运算(寄存器变址),相当于送常数,因为寄存器的值在每次进入调用的函数后是确定的。通过下例可大致看到“数组名”会是一个常数给指针赋值:
1:
#include <stdio.h>
2:
int *p,a[20];
//定义全局变量*p,a[20]
3:
void main()
4:
{
...//一大堆准备工作的汇编码省略
5:
int b;
//定义局部变量b
6:
p=a;
mov
dword ptr [p (00422808)],offset a (004227b8) //将数组名a给指针p,其实是将常数004227b8赋值给p,004227b8是数组a的首地址
7:
p=&a[1];
mov
dword ptr [p (00422808)],offset a+4 (004227bc) //&运算实际上是将常数004227bc给指针p,004227bc是数组a[1]的地址
8:
p=&b;
lea
eax,[ebp-4]
//方括号一般是寻址传值,但lea是传送有效地址指令,方括号内的ebp-4就是有效地址
mov
[p (00422808)],eax
//局部变量&运算,是将寄存器ebp的值减4后送给指针p,ebp的值恒等于栈顶(栈从高位递减)
9:
}
...//一大堆函数返回前的恢复代码省略
ret
[此贴子已经被作者于2015-12-17 23:33编辑过]