这里我借用一下《POINTERS ON C》中8.8问题。 问题如下:
8. 下面的声明取自某个原文件:
int a[10];
int *b = a;
但在另一个不同的源文件中,却发现了这样的代码:
extern int *a;
extern int b[];
int x, y;
...
x = a[3];
y = b[3];
请解释一下,当两条赋值语句执行时会发生什么?(假定整形和指针的长度都是4字节)
我们都知道把语法糖[]拆开就是*(a + 3), *(b + 3)。然后a和b又是赋值过去的,最起码他们的值是相等的
我开始想的是,这两条赋值语句是把a和b的值取出来然后加上3*4的偏移量相对寻址,然后分别赋值给x和y;
依照我的想法形成的汇编代码应该是:
movl 12+a(%rip), %eax
movl %eax, -4(%rbp)
movq 12+b(%rip), %eax
movl 12(%rax), %eax
movl %eax, -8(%rbp)
但我在gcc 下形成的汇编和我想的有那么一点不同
它处理指针和数组的方式是不同的。首先a(指针)它是先提取指针值(这里用到的是a(%rip), 间接提取a的值),a指向的是首个元素,那么最后和12相加的是首个元素的值,假如首个元素值是0x34000那么最后赋值给x的是,*(0x34012)至于这个地址存放的是什么值就未知了。
b(数组)的话,它是先给b加上12然后再间接访问,假设b是0x433300 ,那么最后赋值给y的是*(0x33312)
两者相差甚远!
只有在全局变量上声明错误才会出现这样情况比如:在1.c中声明int a[10];在2.c中声明extern int *a;
我不思其解