5

我有以下测试应用程序:

#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**

4

4 回答 4

3

所有指针的行为都相同,因为您将它们全部声明为char*. C 是静态类型的,因此类型绑定到变量而不是值。

现在解释了行为部分,我们只需要找出为什么它们实际上具有相同的值(根据 %p printf)。好吧,这只是 GCC 将指针实现为内存地址的产物(使 * 与 ** 不同的偏移量和大小调整都由幕后的类型系统/编译器处理)。请注意,就像任何发出警告的最可疑的东西一样,这可能是未定义的行为,或者至少是一种不好的做法:)

于 2011-10-06T03:00:37.867 回答
2

数组不是指针,尽管它们可以以几乎相同的方式使用。您碰巧发现了数组和指针语义不同的一个方面。

于 2011-10-06T02:49:13.240 回答
1

您可以从*&运算符的代数中计算出来。

  • 我们知道这是数组buf的第 0 个元素的地址buf

  • 我们知道这&buf[0]也是第 0 个元素的地址

  • 根据定义buf[0]相当于*(buf+0)

  • 并且&(*(a))等价于a

所以,&buf[0]就变成&(*(buf+0))buf

更新

在这里,让我们把它作为一个证据。

  1. &buf[0] 给定。
  2. &(buf[0])通过 C 优先规则与 () 的
  3. &((*(buf+0)))因为buf[0] == *(buf+0).
  4. &(*(buf+0))消除多余的括号
  5. buf量子点
于 2011-10-06T02:55:27.157 回答
1

如果您考虑一下编译器在处理数组时实际生成了什么代码,就会变得更加清楚。名称 buf 引用数组的第一个(第零个)元素的地址(用于包含字符的连续空间)。如果您在符号表的“buf”条目中查看对象,您会找到第一个元素的地址。例如,当您引用 buf[0] 时,编译器会生成 buf 的地址,加上 char 大小的零倍。这恰好与 buf 本身的地址相同。

于 2011-10-06T03:09:28.300 回答