首页 > 解决方案 > 使用联合时未定义行为的情况

问题描述

我有以下代码来自“C++17 详解”一书:

union Superfloat{
float f;
int i;
}

int RawMantissa(Superfloat f){
return f.i & ((1< 23) -1);
}

int RawExponent(Superfloat f){
return (f.i >> 23)& 0xFF;
}

在该代码之后,Bartlomiej Filipek 先生写道:“然而,虽然上述代码可能在 C99 中工作,但由于更严格的别名规则,它在 C++ 中是未定义的行为”。

我想更好地理解作者这句话的意思,因为我不明白。你能详细给我解释一下吗?

他给出了以下解释(但我需要更多解释):

C.183!... 读取与写入时使用的类型不同的联合成员是未定义的。这种双关语是不可见的,或者至少比使用命名 >cast 更难发现.....

我也不明白那个解释,以及它如何帮助理解上面的代码是未定义的行为。

我将感谢您的深入解释

标签: c++undefined-behavior

解决方案


这很简单。一个工会最多有一个活跃的成员。成员在您写入时变为活动状态。您只能从活动成员中读取。

例子:

union U
{
    float f;
    int i;
};

auto foo_1()
{
    U u; // no member is active

    u.f = 24.5; // write to `u.f` . `u.f` is now the active member

    int i = u.i; // read of `u.i` Since `u.i` is not the active member this is UB in C++
}
auto foo_2()
{
    U u;
    // no active member

    u.f = 24.5; // write to `u.f` . `u.f` is now the active member

    float f = u.f; // read of `u.f` . Ok since `u.f` is the active member

    u.i = 11; // write to `u.i` . `u.i` is now the active member.
              // `u.f` is NOT the active member anymore

    int i = u.i; // ok, read of the active member `u.i`

    float f2 = u.f; // read of `u.f`. UB, since `u.f` is not the active member
}

推荐阅读