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

C标准下类型双关与联合类型访问及转换的合规性问询

C标准中联合类型相关问题解答

背景回顾

C标准(ISO/IEC 9899:201x)的6.5.2.3.9例3给出了利用联合公共初始序列的合法代码:

#include<stdio.h>

union point {
  struct {
    int value;
  } x;
  struct {
    int value;
  } y;
};

int main() {
  union point p;
  p.x.value = 1;
  printf("%d\n", p.y.value);
}

对应的标准条款翻译如下:

为简化联合体的使用,标准做出一项特殊保证:如果联合体包含若干共享公共初始序列的结构体(定义见下文),且当前联合体对象中存储的是这些结构体之一,那么只要联合体的完整类型声明可见,就允许检查任意一个此类结构体的公共初始部分。当两个结构体的一段或多段初始成员具有兼容类型(对于位域,还要求宽度相同)时,它们共享公共初始序列。


问题1:如下代码是否符合C标准规定?

#include<stdio.h>

union point {
  int x;
  int y;
};

int main() {
  union point p;
  p.x = 1;
  printf("%d\n", p.y);
}

完全符合C标准规定。可以将两个int成员视为仅含单个成员的公共初始序列,满足“对应成员类型兼容”的要求。此外,联合的所有成员共享同一存储空间,给p.x赋值后,读取同类型的p.y本质是直接访问该存储区域的int值,这是标准明确允许的操作。

问题2:标准中是否有条款保证对象表示完全依赖于对象类型,从而确保上述代码合法?

是的。C标准(如ISO/IEC 9899:2011的6.2.6.1)规定:同一类型的所有对象具有相同的对象表示(二进制存储格式)。联合的成员共享存储空间,p.x和p.y都是int类型,因此它们的对象表示完全一致,读取p.y就是读取该存储区域的合法int值,标准对此有明确保证。

问题3:该规则是否适用于更复杂的类型(如struct或union)?

适用于符合条件的复杂类型。只要联合中的结构体成员共享公共初始序列,就可以合法跨成员访问。例如:

union demo {
  struct { int a; char b; } s1;
  struct { int a; double c; } s2;
};

s1和s2的第一个成员都是int a,属于公共初始序列,给demo.s1.a赋值后,读取demo.s2.a完全符合标准。

对于联合类型作为成员的情况,只要成员类型兼容或其公共初始序列符合要求,规则同样适用。但如果复杂类型的初始成员类型不兼容,跨成员访问就不符合标准。

问题4:给定如下联合定义,是否可以编写一个签名为union second convert(union first input)的纯函数,使其符合C标准,且无需记住union first中存储的成员类型,即可将匹配成员映射到union second中?

union first {
  int a;
  char b;
};

union second {
  int a; 
  char b;
  float c;
};

可以编写这样的纯函数。union first和union second的前两个成员类型完全兼容,联合的存储共享特性保证了union first的对象表示可以直接对应到union second的前半部分存储。

示例实现:

#include <string.h>

union second convert(union first input) {
  union second res;
  // 直接拷贝整个union first的存储内容到union second
  memcpy(&res, &input, sizeof(union first));
  return res;
}

无论input中存储的是a还是b,拷贝后res.a或res.b都能正确读取对应的值——因为两者的同类型成员对象表示完全一致,无需额外记录输入的成员类型。


内容的提问来源于stack exchange,提问作者Maksymilian Mika

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 16:03:09