一、 之前比较明显的不同
我们已经知道:
- 对数组名取地址,得到的仍然是指向数组第一个元素的指针变量;而对指针变(常)量取地址,得到的是指向指针类型的指针。
- sizeof (数组名),得到的是数组的长度,sizeof (指针变/常量)得到的指针本身的长度
二、在使用链接属性上体现的不同
这一点在《C和指针》这本书中,有所介绍。不过通过编译成汇编代码来看,更容易理解。
extern int *a;
extern int b[];
main() {
int x, y;
x = a[3];
y = b[3];
}
int a[10];
int *b = a;
可以看到在sample1.c中,a被声明为指针变量,b被声明为数组名,而在sample2.c中两者反了过来。由于编译器会对外链的指针变量和数组名进行不同的处理,这样的调换会造成错误。
在sample1.c中,对于被声明为指针变量的a,编译器会对其进行间接访问取得一个指针(所以外链得到的值实际上是指向实际值的指针),然后对这个指针加3得到a[3]的地址,而由于a实际上是一个数组名,经过外链后,a指向的是实际上是数组的第一个元素,所以对其进行间接访问得到的是一个整型值而非指针。
同样的,b被声明为数组,而b实际上是一个指针变量,因此编译器按照指针变量来处理也会引起错误
看一下汇编代码
movq .refptr.a(%rip), %rax
movq (%rax), %rax # 间接访问,在本例中取得取得的实际上是一个整型值,而非指针变量
movl 12(%rax), %eax
movl %eax, -4(%rbp)
movq .refptr.b(%rip), %rax
movl 12(%rax), %eax # refptr.b是一个指向指针的指针,所以这里获取的是一个未知值
movl %eax, -8(%rbp)
产生这种情况的原因在于,refptr.a实际上是&a,refptr.b实际上是&b,由于对指针变量取地址得到指向指针的指针,而对数组名取地址得到的是指向数组第一个元素的指针,因此对于数组和指针变量编译器会进行不同的处理,所以如果混用的话,就会出错。
还好,我觉得这种错误是很少见的,写一下加深印象。
Goodbye guys
|