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 ofT
”的表达式将转换为类型为“pointer toT
”的表达式,其值将是数组中第一个元素的地址。这是在第一次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[]