You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

结构体数组指针打印地址异常及重合问题的技术咨询

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 21:12:31