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

C语言Strict Aliasing与共用体:下述程序是否存在未定义行为?

C17标准下该程序的未定义行为分析

程序代码

#include <stdio.h>

short g(int *p, short *q) {
  short z = *q; *p = 10; return z;
}

int main(void) {
  union int_or_short { int x; short y; } u = { .y = 3 };
  int *p = &u.x;
  short *q = &u.y;
  short r = g(p, q);
  printf("%hd %d\n", r, u.x);
}

结论:存在未定义行为

依据C17标准条款的分析

1. 严格别名规则(C17 §6.5/7)

C17明确规定:对象的值只能通过以下类型的左值访问:

  • 对象的有效类型(即最近一次写入该对象时使用的类型);
  • 与有效类型兼容的有符号/无符号对应类型;
  • 与有效类型兼容的字符类型;
  • 包含上述类型的聚合/联合类型;
  • 指向上述类型的指针(用于访问子对象)。

在这个程序里:

  • 初始化时通过.y(short类型)给联合u赋值,此时u的有效类型是short。
  • 函数g中,先通过short*类型的q读取*q(即u.y),这符合规则,因为访问类型与有效类型一致。
  • 但紧接着通过int*类型的p执行*p = 10(修改u.x),此时u的有效类型还是short,而int和short既不兼容,也不属于规则允许的例外类型,直接违反了严格别名规则,触发未定义行为。

2. 联合成员访问规则(C17 §6.5.2.3/3)

C17对联合的访问补充规定:如果访问联合的成员类型,与最近一次写入联合的成员类型不兼容,且不符合严格别名规则的例外情况,行为未定义。
这里写入u.x(int类型)时,最近一次写入的是u.y(short类型),两者类型不兼容,也不满足例外条件,进一步确认了未定义行为的存在。

补充说明

联合的所有成员共享同一块内存,&u.x和&u.y指向同一地址,但指针类型不同。通过不同类型的指针跨类型修改对象,正是严格别名规则要限制的场景——这种操作会让编译器的优化假设失效,可能导致不可预测的执行结果(比如编译器可能优化掉读取*q的操作,或生成不符合预期的内存访问指令)。

内容的提问来源于stack exchange,提问作者Steve Siegel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 08:32:11