这是一个 GCC 错误,它将 uint128_t 上的按位运算结果存储在位字段中

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

此代码可与 GCC 配合使用,优化程度低于

-O2
或在 clang 中。

constexpr uint16_t KEY_BITS = 70;
constexpr unsigned __int128 KEY_BITS_MASK = (((unsigned __int128) 1) << KEY_BITS) - 1;

struct Entry
{
    unsigned __int128 left : 4;
    unsigned __int128 right : 4;
    unsigned __int128 key : KEY_BITS;
};

Entry data;

void print(unsigned __int128 a)
{
    std::cerr << std::bitset<16>(a >> 64) << std::bitset<64>(a) << std::endl;
}

void store(unsigned __int128 key, uint8_t left, uint8_t right)
{
    data.left = left;
    data.right = right;
    data.key = key & KEY_BITS_MASK;

    print(key & KEY_BITS_MASK);
    print(data.key);

    assert(data.key == (key & KEY_BITS_MASK));
}

在带有

-O2
的 GCC 中,它似乎是未定义的,因为添加或删除打印会改变行为。在“坏”情况下,它首先将
&
运算的结果转换为 64 位整数。

这是一个错误还是我误解了这些类型的行为方式。看起来不应该是未定义的。

编译器浏览器:https://godbolt.org/z/he7Kx6rMr

c++ gcc bit-manipulation compiler-optimization bit-fields
1个回答
0
投票

位域的实现方式是“实现定义的”,而不是 C++ 标准的一部分。这意味着位域可以用额外的位填充,以在内存中对齐它们。这意味着它们不能安全地用于存储实际位。它们仅确保设置和读取的结果的行为就像变量具有指定的位数。

似乎 cppreference bit_field 也包含该信息(查看注释部分)

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