为何p->p1输出1而s2.p1输出0?结构体复制后表现差异问询
首先直接给结论:这是因为结构体赋值是值拷贝操作,*p = s2; 之后,p指向的堆内存结构体和栈上的s2是完全独立的两个实例,修改其中一个的成员不会影响另一个。你看到的差异完全符合预期,而p->p2和s2.p2没有差异,只是因为你没修改s2.p2而已。
详细拆解代码执行流程
结构体初始化:
struct S2 s2 = {1,2,3,0};根据
struct S2的成员顺序(int p1; struct S1 s1; int p2;),这个初始化会完成以下赋值:s2.p1 = 1s2.s1.p1 = 2s2.s1.p2 = 3s2.p2 = 0
内存分配与结构体拷贝:
// 注意:原代码里写的是struct s2(小写),这是语法错误,C语言大小写敏感,应改为struct S2 p = (struct S2 *)malloc(sizeof(struct S2)); *p = s2;malloc在堆上分配了一块与struct S2大小一致的内存,*p = s2执行的是完整的值拷贝:把s2的所有成员变量的值,逐一复制到p指向的堆内存区域。此时,堆上的结构体和栈上的s2是完全独立的两个实体,拥有不同的内存地址,修改其中一个的成员变量,不会对另一个产生任何影响。修改s2的p1成员:
s2.p1 = 0;这行代码仅修改了栈上
s2结构体的p1成员,堆上p指向的结构体的p1成员依然保留拷贝时的原值1,所以后续打印会出现p->p1=1、s2.p1=0的差异。为什么p->p2和s2.p2没有差异?
原因很简单:你从始至终都没有修改过s2.p2的值,它从初始化后一直是0;而p->p2在拷贝时也继承了这个0,所以两者的值自然相同。如果你添加一行s2.p2 = 5;,再打印两个值,就会看到p->p2还是0,s2.p2变成5,和p1的表现完全一致。
代码里的小错误提醒
原代码中malloc的强制类型转换写了struct s2(小写),C语言是大小写敏感的,编译器会认为s2是未定义的结构体类型,导致编译报错,应该修正为struct S2。
内容的提问来源于stack exchange,提问作者Noel Nosse

