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

C语言函数return与赋值的语义差异及标准示例UB问题咨询

问题解释

触发UB的直接赋值场景

你提到的「直接赋值」指将示例中的函数调用替换为直接读取另一个union成员的写法:

// 该写法触发UB
g.u2.f3 = g.u1.f2;

直接赋值触发UB的核心原因

  • 首先union内的两个结构体u1、u2没有符合标准要求的公共初始序列:u1的首成员是int f1,u2的首成员是struct s f3,二者类型完全不匹配,不满足C标准对union共享公共前缀的成员互访豁免条款。
  • 两个赋值操作数对应的存储区域完全重叠:u1.f2在union内的偏移是int类型的大小,u2.f3在union内的偏移是0,二者的存储范围完全重合,属于对同一块存储通过两个不兼容的类型别名同时进行读、写操作,违反严格别名规则,因此属于未定义行为。
  • 补充:C标准没有规定赋值操作左右操作数的求值顺序,对g.u1.f2的读和对g.u2.f3的写是未序列的,可能出现写操作提前覆盖尚未读完的存储区域的情况,进一步加剧了行为的不确定性。

函数返回写法合法的原因

  • 函数f执行return g.u1.f2时,会先完整读取g.u1.f2的值,将其拷贝到与返回类型struct s对应的独立临时对象中,此时对uniong的读取操作已经完全结束,临时对象的存储与uniong完全无关。
  • 后续执行g.u2.f3 = f()时,仅将独立临时对象的完整值写入g.u2.f3,不存在对uniong的同时读写,且写入操作会合法切换union的活跃成员为u2,全程没有违反标准规则。

标准规定不存在矛盾的原因

你引用的规定:

如果表达式的类型与所在函数的返回类型不同,该值会被转换,效果等同于对具有该函数返回类型的对象执行赋值操作。
这条规定仅约束return语句中的值类型转换语义,和存储访问时序、别名规则没有任何关系:它只是说明return 表达式中,将表达式结果转换为返回类型的规则,和返回类型对象 = 表达式的转换规则完全一致,并没有声明return+赋值的完整流程和直接赋值的存储访问逻辑等价,因此不存在矛盾。

内容的提问来源于stack exchange,提问作者Some Name

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 17:48:03