使用 union 在 C 中输入双关语
Type punning in C using union
考虑以下代码:
union u{
int i;
long j[2];
};
int main(void){
union u *u = malloc(sizeof *u);
u->i = 10;
printf("%li\n", u->j[0]);
}
我想用6.5
解释代码的合法性:
An object shall have its stored value accessed only by an lvalue
expression that has one of the following types:
— a type compatible with the effective type of the object,
[...]
— an
aggregate or union type that includes one of the aforementioned types
among its members (including, recursively, a member of a subaggregate
or contained union), or
将此应用于上面的示例我们有:
u->i = 10;
使 u->i
对象具有有效类型 int
。
- 左值
u
有一个 union
类型,其中包含类型 int
. 的成员
- 具有未指定值的对象
u->j[0]
使用具有类型 int
. 成员的 union u
类型的左值 u
进行访问
- 应用引用
6.5
我们知道这里没有 UB。
问题:这样的推理是否正确?或者它有什么错误?
是的,你的推理是正确的。这不是未定义的行为,而是根据 C11 第 6.2.6.1/7 节的未指定行为:
When a value is stored in a member of an object of union type, the
bytes of the object representation that do not correspond to that
member but do correspond to other members take unspecified values.
第 3.19.3 节阐明了这意味着什么:
unspecified value: valid value of the relevant type where this International Standard imposes no requirements on which value is
chosen in any instance
附件 J:可移植性问题
中提醒了这一点
J.1 Unspecified behavior
1 The following are unspecified:
— ...
— The value of padding bytes when storing values in structures or
unions (6.2.6.1).
— The values of bytes that correspond to union
members other than the one last stored into (6.2.6.1).
— ...
J2 中未指定任何有关访问联合成员的内容,这是关于未定义行为的
话虽这么说,可移植性问题可能会很严重,如第 6.2.6.1/6 节提醒的那样:
The value of a structure or union object is never a trap
representation, even though the value of a member of the structure or
union object may be a trap representation.
陷阱表示是“不需要表示对象类型值的对象表示”(定义),理解为“获取陷阱表示 可能会执行陷阱 但不需要 ”(脚注)。所以访问 inactive 值可能会导致程序中断,但如果没有,那只是没有保证。
考虑以下代码:
union u{
int i;
long j[2];
};
int main(void){
union u *u = malloc(sizeof *u);
u->i = 10;
printf("%li\n", u->j[0]);
}
我想用6.5
解释代码的合法性:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
— a type compatible with the effective type of the object,
[...]
— an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
将此应用于上面的示例我们有:
u->i = 10;
使u->i
对象具有有效类型int
。- 左值
u
有一个union
类型,其中包含类型int
. 的成员
- 具有未指定值的对象
u->j[0]
使用具有类型int
. 成员的 - 应用引用
6.5
我们知道这里没有 UB。
union u
类型的左值 u
进行访问
问题:这样的推理是否正确?或者它有什么错误?
是的,你的推理是正确的。这不是未定义的行为,而是根据 C11 第 6.2.6.1/7 节的未指定行为:
When a value is stored in a member of an object of union type, the bytes of the object representation that do not correspond to that member but do correspond to other members take unspecified values.
第 3.19.3 节阐明了这意味着什么:
unspecified value: valid value of the relevant type where this International Standard imposes no requirements on which value is chosen in any instance
附件 J:可移植性问题
中提醒了这一点J.1 Unspecified behavior
1 The following are unspecified:
— ...
— The value of padding bytes when storing values in structures or unions (6.2.6.1).
— The values of bytes that correspond to union members other than the one last stored into (6.2.6.1).
— ...
J2 中未指定任何有关访问联合成员的内容,这是关于未定义行为的
话虽这么说,可移植性问题可能会很严重,如第 6.2.6.1/6 节提醒的那样:
The value of a structure or union object is never a trap representation, even though the value of a member of the structure or union object may be a trap representation.
陷阱表示是“不需要表示对象类型值的对象表示”(定义),理解为“获取陷阱表示 可能会执行陷阱 但不需要 ”(脚注)。所以访问 inactive 值可能会导致程序中断,但如果没有,那只是没有保证。