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

时间:2011-10-09 23:07:38

标签: c

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

struct packet {
  int a;
  char data[500];
};
typedef struct packet packet_t;

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

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

有没有人对此有好的解释?

5 个答案:

答案 0 :(得分:7)

在大多数情况下,类型为“N-element array of T”的表达式将转换为“指向T的指针”类型的表达式,其值将是数组中的第一个元素。这是第一个printf电话中发生的情况;类型为packet.data的表达式char [500]将替换为char *类型的表达式,其值为第一个元素的地址,因此您可以有效地打印{{1 }}。

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

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

void *

答案 1 :(得分:4)

那是因为数组衰减到指向序列中第一个元素的指针。因此,packet.data地址位置与&packet.data&packet.data[0]相同。

答案 2 :(得分:1)

我不知道为什么这会被拒绝,这是一个很好的问题,暴露了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[]

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

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

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

答案 3 :(得分:0)

根据 C11 (6.3.2.1.3) 部分。 当数组用作 sizeof 和一元 & 运算符的操作数时,数组会衰减为指向其第一个元素的指针

因此 packet.data 不会在表达式 &packet.data[0] 中衰减为 &packet.data。结果将是一个 char (*)[500] 类型的指针,并且在数字上与其第一个元素的地址 packet.data[0] 相同。

答案 4 :(得分:-2)

因为除了使& packet.data导致编译错误之外,这是唯一合理的做法。整数a和数据字符数组按顺序排列在堆栈中,不涉及解除引用。