我有以下测试应用程序:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(void){
char buf[512];
buf[0]= 0x1;
buf[1]= 0x2;
char *temp1 = &buf;
char *temp2 = buf;
char *temp3 = &buf[0];
printf("temp1:%p, temp2:%p, temp3:%p\n",temp1,temp2,temp3);
printf("0 = %d, %d, %d\n",temp1[0],temp2[0],temp3[0]);
printf("1 = %d, %d, %d\n",temp1[1],temp2[1],temp3[1]);
return;
}
它汇编了警告:
gcc ./testptr.c -o testptr
./testptr.c: In function ‘main’:
./testptr.c:9: warning: initialization from incompatible pointer type
但是当我运行它时,所有三个指针的行为都相同。
./testptr
temp1:0x7fff3a85f220, temp2:0x7fff3a85f220, temp3:0x7fff3a85f220
0 = 1, 1, 1
1 = 2, 2, 2
我知道buf == &buf[0]
,但为什么&buf == &buf[0]
? &buf
不应该是char**
吗?
答案 0 :(得分:3)
所有指针的行为都相同,因为您声明所有指针都是char*
。 C是静态类型的,因此类型绑定到变量而不是值。
现在解释了行为部分,我们只需要找出它们实际上具有相同值的原因(根据%p printf)。好吧,这只是一个由GCC实现为内存地址的指针工件(偏移量和大小调整使*与**不同都是由幕后类型系统/编译器处理的)。请注意,与任何发出警告的最可疑的东西一样,这可能是未定义的行为,或者至少是一种不好的做法:)
答案 1 :(得分:2)
数组不是指针,尽管它们可以以相同的方式使用。您碰巧找到了一个方面,其中数组和指针语义不同。
答案 2 :(得分:1)
您可以从*
和&
运算符的代数中进行处理。
我们知道buf
是buf
数组的第0个元素的地址
我们知道&buf[0]
也是第0个元素的地址
根据定义buf[0]
相当于*(buf+0)
和&(*(a))
相当于a
。
因此,&buf[0]
变为&(*(buf+0))
,即buf
。
的更新强> 的
在这里,我们将其作为证明。
&buf[0]
鉴定。&(buf[0])
由C优先规则与()的&((*(buf+0)))
因为buf[0] == *(buf+0)
。&(*(buf+0))
消除外来的阴影buf
QED 答案 3 :(得分:1)
如果您考虑编译器在处理数组时实际生成的代码,则会更加清晰。名称buf引用数组的第一个(第0个)元素的地址(包含字符的连续空格)。如果您在符号表的“buf”条目中查找对象,您将找到该第一个元素的地址。当你引用例如buf [0]时,编译器会生成buf的地址,加上char的大小的零倍。这恰好与buf本身的地址相同。