数组和指针
指针和数组有什么区别?
C程序(array.c):
#include <stdio.h>
int main()
{
int date[3] = {2012,11,11};
int *p = date;
int a = date[1];
int b = p[1];
printf("a:%d b:%d\n", a, b);
printf("date:%p\np :%p\n", date, p);
return 0;
}
汇编及注释:
| |
| |
| |
|
大家对 lea 指令可能比较陌生,它跟 mov 指令很像,不过 lea 指令传递的是内存的地址,而 mov 指令传递的的是内存的值,例如:
leal 24(%esp), %eax # 将 24+esp 的结果给 eax
movl 24(%esp), %eax # 将 2012 给 eax
总结
首先,我们看到 main 也是一个函数,它编译后的汇编代码跟函数调用中分析过的 Double 函数有一样的结构。
其次,指针是有存储空间的(32位机是4个字节的大小),其中存储的是一个内存地址;而数组只有数组中的元素有存储空间,而 C 代码中经常用到的数组首地址(用数组名来代替)可以说是没有存储空间的。假设将数组首地址赋值给一个指针,数组首地址的存在形式是:
- 如果是全局数组,它将是 mov 指令中的一个立即数(常量)
- 如果是局部数组,它将是 lea 指令中由 esp 或 ebp + 常量计算的结果
所以数组的首地址是一条机器指令的操作数,不在局部变量空间中,也不在全局变量空间中,而是被固化在代码中。因此,数组首地址不能被更改。
printf 函数的调用跟别的函数一样:先传参数,然后 call printf,打印指针都可以使用 %p 格式描述符。程序的运行结果如下:
[lqy@localhost temp]$ gcc -o array array.c
[lqy@localhost temp]$ ./array
a:11 b:11
date:0xbf9c3b68
p :0xbf9c3b68
[lqy@localhost temp]$
date 和 p 的值都是 date 数组的首地址。