gpt4 book ai didi

c++ - 使用 union 的一个字段的地址访问另一个字段是否合法?

转载 作者:可可西里 更新时间:2023-11-01 16:04:38 27 4
gpt4 key购买 nike

考虑以下代码:

union U
{
int a;
float b;
};

int main()
{
U u;
int *p = &u.a;
*(float *)p = 1.0f; // <-- this line
}

我们都知道 union 字段的地址通常是相同的,但我不确定这样做是否是明确定义的行为。

因此,问题是:像上面的代码一样强制转换和取消引用指向 union 字段的指针是否合法且定义明确的行为?


附言我知道它更像是 C 语言而不是 C++,但我想了解它在 C++ 中是否合法,而不是 C。

最佳答案

联盟的所有成员必须位于同一地址,这是标准所保证的。您正在做的确实是明确定义的行为,但应该注意的是,您不能使用相同的方法从 union 的非事件成员中读取数据。

Note: Do not use c-style casts, prefer reinterpret_cast in this case.


只要您所做的只是写入union 的其他数据成员,行为就是明确定义的;但如前所述,这种变化被认为是 unionactive 成员;这意味着您以后只能读取刚刚写入的内容。

union U {
int a;
float b;
};

int main () {
U u;
int *p = &u.a;
reinterpret_cast<float*> (p) = 1.0f; // ok, well-defined
}

Note: There is an exception to the above rule when it comes to layout-compatible types.


问题可以改写为以下片段,这在语义上等同于“问题”的简化版本。

#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
}

标准 ( n3797 ) 说了什么?

9.5/1    <b>Unions</b>    [class.union]

In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static dat amembers ca nbe stored in a union at any time. [...] The size of a union is sufficient to contain the largest of its non-static data members. Each non-static data member is allocated as if it were the sole member of a struct. All non-static data members of a union object have the same address.

Note: The wording in C++11 (n3337) was underspecified, even though the intent has always been that of C++14.

关于c++ - 使用 union 的一个字段的地址访问另一个字段是否合法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33056403/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com