考虑下面的工会:我们可以使用工会进行类型转换吗?
union{
uint32_t a;
uint64_t b;
};
两个a
和b
驻留在同一存储区域。如果我们将32位整数a
初始化为某个值,那么如何获得b
(当b
未初始化时)?这是否意味着,编译器在内部转换a到b
感谢
考虑下面的工会:我们可以使用工会进行类型转换吗?
union{
uint32_t a;
uint64_t b;
};
两个a
和b
驻留在同一存储区域。如果我们将32位整数a
初始化为某个值,那么如何获得b
(当b
未初始化时)?这是否意味着,编译器在内部转换a到b
感谢
在uint64_t
额外的字节将有一个未确定的值。
从C standard的节6.2.6.1:
当值被存储在联合类型的对象的一员,所述对象表示的不 字节对应于会员,但确实与其他会员取得 未指定的值。
而第6.5.2.3:
后缀表达式接着
.
操作者和标识符指定结构或联合对象的成员。 值是指定成员的值,95)并且如果 是第一个表达式是左值,则该值为左值。如果第一个表达式 具有限定类型,结果具有 所谓合格版本指定构件95)如果构件用于读取联合对象的内容的类型不一样成员最后用于在对象中存储值 值的对象表示的相应部分是 在6.2.6中描述的新类型中重新解释为对象表示形式为 (有时称为“类型双引号” )。 这可能是一个陷阱表示。
唯一允许的是如果您有一个或多个结构体的联合体,并且每个结构体都具有相同类型的初始成员。
从部分6.5.2.3:
一个特殊的保障是为了简化使用工会提出:如果一个联合包含共享 公共初始序列几种结构(见下文) ,并且如果联合对象 当前包含这些结构中的一个,则允许 检查联合体的完成类型的声明可见的任何位置的任何公共初始部分。如果对应的 成员对于一个或多个初始成员的序列具有兼容类型(以及对于位域相同的宽度) ,则两个 结构共享共同的初始序列。
下面是一个例子,这可能是有用的:在不同类型的插槽
union sockadddr_u {
struct sockaddr sa;
struct sockaddr_un sun;
struct sockaddr_in sin;
}
这些结构存储信息。大多数成员不同,但每个成员的第一个成员的类型为sa_family_t
,它告诉您套接字类型。这允许您检查这些成员中的第一个成员,以确定哪些成员包含其内部成员的有意义数据。
它真的是UB吗?我的意思是:是不是一个平台依赖和实现定义的行为? – LPs
未指定的值不是不确定的值。该标准还明确允许通过联合http://port70.net/~nsz/c/c11/n1570.html#note95进行类型双击。如果目标类型具有陷阱表示,则它定义了非常多的实现(而不是UB)。 – StoryTeller
@dbush谢谢你'它们中任何一个的共同初始部分'意味着两个结构具有相同的字段(结构的所有字段相同的类型和相同的数字)。但是为什么我会有一个类似的结构的联盟,那会是什么样的使用呢? – Bionix1441
我很确定编译器不会转换任何东西,而这样做是未定义的行为。 – melpomene
将'a'设置为'int',在内存中写入4个字节。访问'b'你正在读取4个字节的内存作为'float':有什么问题? – LPs
@LPs我在32位平台上。 – Bionix1441