我有一个看起来像这样的结构:
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)
有没有人对此有一个很好的解释?
在大多数情况下,类型为"N-element array of T
"的表达式将转换为"指向T
" 的类型的表达式,其值将是数组中第一个元素的地址.这是第一次printf
通话中发生的事情; 表达packet.data
,其具有型char [500]
,替换类型的表达式char *
,并且它的值是所述第一元件的地址,所以你有效打印&packet.data[0]
.
当数组表达式是一元运算&
符的操作数时,会出现此规则的一个例外; 表达式的类型&packet.data
是char (*)[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 会生成某种编译时错误。