结构体数组指针打印地址异常及重合问题的技术咨询
C语言结构体数组printf打印地址异常问题解析
示例代码
struct Student{ int roll; char name[8]; float marks; }; void main(){ struct Student stu[5] = {{10,"xyz",30},{15,"abc",50},{20,"lmn",70}}; printf("%d \n", (*stu).roll); printf("%d \n", (*(stu+1)).roll); printf("%x %x\n", (*stu), (*(stu+1))); // <- here (a) printf("%x \n", (*(stu+1))); // <-here (b) printf("%x \n", (stu)); printf("%x \n", (stu+1)); }
运行输出
10 15 351ff8c0 351ff8b0 351ff8c0 351ff8d0 351ff8e0
疑问解答
1. 为什么(*(stu+1))在标记(a)和(b)的printf语句中打印出不同的地址?
核心原因是你用了错误的格式符%x去打印结构体对象,这属于C语言的未定义行为——%x要求对应参数是unsigned int类型,但你传递的是整个结构体,printf会错误解析栈上的参数。
- 在(a)的调用中,你传入了两个
struct Student对象,每个结构体在栈上占用16字节(int(4)+char8+float(4),内存对齐后总大小16字节)。printf按%x的要求,从栈中依次读取两次4字节数据,这两次读取的是两个结构体内容的前4字节。 - 在(b)的调用中,你只传入了一个结构体对象,栈上仅压入16字节数据。printf读取的是这个结构体内容的前4字节。
由于两次调用的栈参数布局完全不同,读取到的自然是不同的数值,看起来像不同的地址,但本质是无意义的随机数据。
2. 为什么标记(b)中(*(stu+1))的地址与(*stu)的地址相同?
这是个假象——你打印的根本不是结构体的地址。你传递给printf的是结构体对象本身,而非结构体的指针。如果要打印结构体的地址,应该传递指针(比如&(*stu)或stu),并使用标准指针格式符%p。
你用%x打印结构体对象时,printf只是把栈上结构体内容的前4字节当成无符号整数输出,这个值刚好和(a)中第一个结构体对应的栈数据相同,完全是巧合,属于未定义行为导致的随机结果。
正确打印方式示例
// 正确打印结构体地址的代码 printf("%p \n", (void*)stu); // 第一个结构体的地址 printf("%p \n", (void*)(stu+1)); // 第二个结构体的地址 printf("%p \n", (void*)&(*stu)); // 和stu等价 printf("%p \n", (void*)&(*(stu+1))); // 和stu+1等价
内容的提问来源于stack exchange,提问作者yogesh
相关产品推荐
相关产品推荐

