直接通过 memcpy() 或 std::bit_cast() 创建的联合的活动成员?

问题描述 投票:0回答:1

考虑以下代码:

#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个问题:

  1. u
    中的哪个成员在
    auto r = ...
    线之前处于活动状态?

  2. 哪一行有未定义的行为(如果有),为什么?

  3. true
    翻转到
    false
    是否会改变上面的答案,如果是的话,如何/为什么?

c++ language-lawyer union c++20
1个回答
0
投票

u 的哪个成员在 auto r = ... 行之前处于活动状态?

默认初始化的

u
没有任何活动成员。

std::bit_cast
隐式创建嵌套在返回对象中的对象。仅当
std::bit_cast
的隐式对象创建启动子对象之一的生命周期时,成员才会处于活动状态。仅当隐式对象创建能够提供程序执行定义的行为时,才指定执行此操作。

但是,无论哪个子对象的成员隐式对象创建将启动生命周期,

r += u.i[1];
r += u.ull;
都会具有未定义的读取非活动成员的行为。

因此,无论如何,该程序都具有未定义的行为,并且

u
中没有任何成员处于活动状态。

哪一行有未定义的行为(如果有),为什么?

各个线路不能有未定义的行为。整个程序要么有未定义的行为(对于给定的输入),要么没有。

在所有行都存在的情况下,程序具有未定义的行为,但是删除那些访问

u.ull
或所有访问
u.i
的行将给出程序定义的行为,因为
std::bit_cast
的隐式对象创建将使其余成员处于活动状态。

将 true 翻转为 false 是否会改变上面的答案,如果是的话,如何/为什么?

同样的问题仍然存在。

std::memcpy
还按照相同的规则隐式创建嵌套在目标中的对象。

© www.soinside.com 2019 - 2024. All rights reserved.