C 数组地址-有与无与的区别

C 数组地址-有与无与的区别,c,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", &

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

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
}

有人对此有很好的解释吗?

这是因为数组衰减为指向序列中第一个元素的指针。因此,
packet.data
地址位置与
&packet.data
&packet.data[0]
相同,因为除了使&packet.data导致编译错误之外,这是唯一合理的操作。整数a和数据字符数组在堆栈中按顺序排列,不涉及解引用。

在大多数情况下,类型为“N-element array of
T
”的表达式将转换为类型为“pointer to
T
”的表达式,其值将是数组中第一个元素的地址。这是在第一次
printf
调用中发生的情况;表达式
packet.data
,其类型为
char[500]
,被替换为
char*
类型的表达式,其值是第一个元素的地址,因此可以有效地打印
&packet.data[0]

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

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


我不知道为什么这被否决了,这是一个很好的问题,暴露了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位桌面系统上,为
数据
分配了4个字节,这是指向100个字符的指针<代码>数据,指针本身就存在于内存中的某个地方

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

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

根据C11(6.3.2.1.3)节。 数组衰减为指向其第一个元素的指针,除非它们用作
sizeof
和一元
&
运算符的操作数


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

您的意思是“为什么两行给出相同的结果”,还是“为什么每个函数调用的结果相同”?前者很容易(因为指针指向同一个对象),而后者则很难区分。如果不使用括号按名称引用数组,它将伪装为指向第一个元素的指针。但这两个元素的可能重复类型是不同的:前者是指向数组的指针,后者是指向字符的指针。两者恰好在同一个数字地址。这个答案可能不正确。我尝试运行代码(GCC 4.8),它和C和C++中的OP代码完全相同的行为;i、 e.“&arr”与&(arr[0])相同,无论数组是单独声明的还是作为结构的成员声明的。@EmilyChen是对的。具体地说,这个答案中的代码片段执行与问题相同的操作,但没有结构,仍然会打印两次相同的地址。因此,结构如何存储数组与问题之间的关系似乎没有什么特别之处<代码>和数据
其中
数据
不在结构中,它不是指向第一个元素的指针,它只是指向第一个元素的指针,当两者都转换为
(void*)
时,它与
数据
相同。
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[]