考虑以下代码:
union U
{
int a;
float b;
};
int main()
{
U u;
int *p = &u.a;
*(float *)p = 1.0f; // <-- this line
}
Run Code Online (Sandbox Code Playgroud)
我们都知道联合字段的地址通常是相同的,但是我不确定它是否是定义良好的行为来做这样的事情.
因此,问题是:在上面的代码中,如何转换和取消引用指向union字段的指针是合法且定义明确的行为吗?
PS我知道它比C++更多C,但我试图理解它是否在C++中是合法的,而不是C.
工会的所有成员必须居住在同一地址,这是由标准保证的.你所做的确实是明确定义的行为,但应该注意的是,你不能使用相同的方法从联盟的非活动成员中读取.
注意:不要使用c风格的演员表,
reinterpret_cast在这种情况下更喜欢.
只要您所做的只是写入其他数据成员union,行为就是明确定义的; 但正如所述,这种变化被认为是其中的积极成员union; 这意味着你以后只能阅读你刚才写的内容.
union U {
int a;
float b;
};
int main () {
U u;
int *p = &u.a;
reinterpret_cast<float*> (p) = 1.0f; // ok, well-defined
}
Run Code Online (Sandbox Code Playgroud)
注意:当涉及布局兼容类型时,上述规则有一个例外.
这个问题可以改写成下面的代码片段,它在语义上等同于"问题"的简化版本.
#include <type_traits>
#include <algorithm>
#include <cassert>
int main () {
using union_storage_t = std::aligned_storage<
std::max ( sizeof(int), sizeof(float)),
std::max (alignof(int), alignof(float))
>::type;
union_storage_t u;
int * p1 = reinterpret_cast< int*> (&u);
float * p2 = reinterpret_cast<float*> (p1);
float * p3 = reinterpret_cast<float*> (&u);
assert (p2 == p3); // will never fire
}
Run Code Online (Sandbox Code Playgroud)
n3797)说什么?Run Code Online (Sandbox Code Playgroud)9.5/1 Unions [class.union]在联合中,至多一个非静态数据成员可以在任何时间处于活动状态,即,至多一个非静态数据成员的值可以随时存储在并集中.[...] union的大小足以包含其中最大的非静态数据成员.每个非静态数据成员都被分配,就好像它是结构的唯一成员一样.union对象的所有非静态数据成员都具有相同的地址.
| 归档时间: |
|
| 查看次数: |
922 次 |
| 最近记录: |