2011-11-20 55 views
4

如果我有这样的标准布局类型:联盟是标准布局类型吗?

struct sl_t 
{ 
    int a; 
}; 

和工会这样的:

union un_t 
{ 
    int b; 
    double q; 
}; 

我可以投的,并使用工会与结构类型?也就是说,我可以假设联盟本身是一种标准布局类型,并且数据在内存开始时是一致的吗?

un_t obj; 
sl_t * s = reinterpret_cast<sl_t*>(&obj); 
s->a = 15; 
assert(obj.b == 15); 

或者我必须把联合变量&obj.b的地址?

请注意,我已经意识到,如果我存储结构中的工会内部的C++ 11标准保证我可以访问两个sl_t ::和un_t :: B,指的是9.5-1。

+2

但是......是不是'&obj.b'都短,更安全吗?我很好奇你的动机。 –

+0

我仍然需要围绕它的reinterpret_cast。我主要好奇,但我确实有一个情况,它可以方便地依靠这个。 –

回答

3

似乎对准您的问题,看看pragma pack。 struct/union名称只是引用已分配的内存块,如果st_t.a在结构中通过添加更多成员而被置换,则您的投射将失败,但如果它仍然是第一个成员,它将起作用,因为联合的所有成员指向与工会本身的地址相同。

请参阅C++标准9.2.17-21节: “指向标准布局结构对象的指针,使用reinterpret_cast适当转换,指向其初始成员(或者如果该成员是位域,然后到它所在的单位),反之亦然。“

另请参见章节9.5联合: “1.在一个联合中,最多有一个非静态数据成员可以在任何时候处于活动状态,也就是说,最多可以有一个非静态数据会员可以在任何时候被存储在一个工会[注:有一个特殊的保证是为了简化使用工会提出:如果标准布局工会包含共享一个公共初始序列(9.2)几个标准布局结构,如果此标准布局联合类型的对象包含其中一个标准布局结构,则允许检查任何标准布局结构成员的公共初始序列;参见9.2。 - 结束注释]联合的大小足以包含其最大的非静态数据成员,每个非静态数据成员都被分配好像它是结构的唯一成员。“

+0

我有兴趣知道,没有任何编译器扩展,它是否有效。 –

+0

@ edA-qa mort-ora-y:我扩展了我的答案,是的,它是有效的,但正如我解释的那样。 – slashmais

+1

你的第二个评论,在标准中它确实保证工会成员的地址与地址本身相同?这是我未能找到的,但是,这会使我的转换有效。是的,显然,如果st_t.a不再是第一个成员,它将无法工作。 –