考虑以下代码:
#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
是否会改变上面的答案,如果是的话,如何/为什么?
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
还按照相同的规则隐式创建嵌套在目标中的对象。