数组的地址 - 具有&符号和没有&符号之间的区别

Ale*_*lec 8 c

我有一个看起来像这样的结构:

struct packet {
  int a;
  char data[500];
};
typedef struct packet packet_t;
Run Code Online (Sandbox Code Playgroud)

我有点困惑为什么以下代码为每个printf输出相同的地址:

void myfunction() {
  packet_t packet;
  printf("%p\n", packet.data);   //e.g., outputs 0x7fff1c323c9c
  printf("%p\n", &packet.data);  //e.g., outputs 0x7fff1c323c9c
}
Run Code Online (Sandbox Code Playgroud)

有没有人对此有一个很好的解释?

Joh*_*ode 8

在大多数情况下,类型为"N-element array of T"的表达式将转换为"指向T" 的类型的表达式,其值将是数组中第一个元素的地址.这是第一次printf通话中发生的事情; 表达packet.data,其具有型char [500],替换类型的表达式char *,并且它的值是所述第一元件的地址,所以你有效打印&packet.data[0].

当数组表达式是一元运算&符的操作数时,会出现此规则的一个例外; 表达式的类型&packet.datachar (*)[500](指向500个元素数组的指针char).

数组的地址与第一个元素的地址相同,因此两个调用都printf显示相同的 ; 只是表达式的类型不同.要迂腐,两个表达式都应该void *printf调用中%p转换(转换说明符需要void *参数):

printf("%p\n", (void *) packet.data);
printf("%p\n", (void *) &packet.data);
Run Code Online (Sandbox Code Playgroud)


小智 -2

我不知道为什么这个被否决了,这是一个很好的问题,暴露了 C 的令人困惑的行为。

之所以会出现混乱,是因为通常在定义数组时会创建一个真正的指针:

char data[100];
printf("%p\n", data);    // print a pointer to the first element of data[]
printf("%p\n", &data);   // print a pointer to a pointer to the first element of data[]
Run Code Online (Sandbox Code Playgroud)

因此,在典型的 32 位桌面系统上,为 分配了 4 个字节data,它是一个指向 100 个字符的指针。Data,指针本身存在于内存中的某个位置。

当您在结构中创建数组时,不会分配指针。相反,编译器packet.data在运行时将引用转换为指针,但不分配任何内存来存储它。相反,它只是使用&packet + offsetof(data).

就我个人而言,我希望语法保持一致并需要一个&符号,而 packet.data 会生成某种编译时错误。

  • 这个答案是*完全错误的*:下面John Bode的答案是正确的答案,tstanisl的答案引用了C11标准的相关部分。 (3认同)
  • 这个答案可能不正确。我尝试运行代码(gcc 4.8),它与 C 和 C++ 中的 OP 代码具有完全相同的行为;即“&arr”与 &(arr[0]) 相同,无论数组是单独声明还是作为结构体成员声明。 (2认同)