提问人:user541686 提问时间:10/1/2023 最后编辑:timrauuser541686 更新时间:10/1/2023 访问量:94
直接通过 memcpy() 或 std::bit_cast() 创建的工会的活跃成员?
Active member of a union created directly through memcpy() or std::bit_cast()?
问:
请考虑以下代码:
#include <stdint.h>
#include <string.h>
#include <bit>
union U
{
uint64_t ull;
int32_t i[2];
};
int main(int argc, char *argv[])
{
uint64_t x = argc;
U u;
if (true)
u = std::bit_cast<U>(x);
else
::memcpy(&u, &x, sizeof(x));
auto r = u.i[0];
r += u.i[1];
r += u.ull;
return r;
}
我有 3 个问题:
哪个成员紧挨着行处于活动状态?
u
auto r = ...
哪些行具有未定义的行为(如果有),为什么?
翻转是否会改变上面的答案,如果是这样,如何/为什么?
true
false
答:
在自动 r = ...线?
default-initialized 没有任何活动成员。u
std::bit_cast
隐式创建嵌套在返回对象中的对象。仅当 的隐式对象创建开始其中一个子对象的生存期时,成员才会处于活动状态。隐式对象创建被指定为仅在将提供程序执行提供定义行为时才执行此操作。std::bit_cast
但是,无论哪个子对象的成员,隐式对象创建都将启动生存期,或者具有读取非活动成员的未定义行为。r += u.i[1];
r += u.ull;
因此,无论 OR 如何,程序都具有未定义的行为,并且没有 成员处于活动状态。u
哪些行具有未定义的行为(如果有),为什么?
单个行不能具有未定义的行为。整个程序要么具有未定义的行为(对于给定的输入),要么没有。
当所有行都存在时,程序具有未定义的行为,但删除那些访问或访问的行将赋予程序定义的行为,因为隐式对象的创建将使另一个成员处于活动状态。(假设联合的复制分配旨在使同一成员在目标中处于活动状态,而在源中处于活动状态。我似乎不清楚这方面的规范。例如,参见 https://github.com/cplusplus/draft/issues/5193 中的讨论。u.ull
u.i
std::bit_cast
)
从真到假会改变上面的答案吗,如果是这样,如何/为什么?
同样的问题仍然存在。 此外,还会通过相同的规则隐式创建嵌套在目标中的对象。memcpy
此外,根据所涉及类型的输入和实现定义的表示,无论上述情况如何,都可能导致未定义的行为,从而在有符号积分算术上溢出。r += u.i[1];
评论
r
int32_t
r += s.ull
union
S s
struct
U
union
:)