为什么C++逐位AND运算符在不同大小的操作数中表现为这样

Why does the C++ bitwise AND operator behave like this with different-sized operands?

本文关键字:操作数 AND 逐位 C++ 运算符 为什么      更新时间:2023-10-16

我很好奇在使用互补operator ~移除位时,类型大小是否是一个因素,最终得到了一个奇怪的结果:

uint64_t x = 0xccccccccccccccccUL;
uint8_t y = 10;
auto z = ~y; // Debugger calls z an 'int' with value of 0xfffffff5
x &= z;
// x is now the correct value: 0xccccccccccccccc4

operator &如何返回大于任意一个操作数的值?

下面的例子让我更加困惑,因为它看起来是相同的逻辑,但产生了不同的结果:

uint64_t x = 0xccccccccccccccccUL;
x &= 0xfffffff5;
// Now x is 0x00000000ccccccc4

这是怎么解释的?不管类型大小/符号如何,使用x &= ~y删除位实际上安全吗?

您正在执行两个加宽操作。第一个是~,它(像任何算术运算符一样(执行标准的"整数提升"。在这种情况下,由于源类型(uint8_t(的所有值都可以放在int中,所以这就是执行的提升。正如您所注意到的,z被推导为具有类型int

第二个加宽操作是&=,在这种情况下它等效于x = x & zuint64_t不适合intunsigned int,甚至不适合int64_t,但uint64_tint都适合uint64_t,所以这是所选的类型。加宽(有符号的(int涉及符号扩展,所以这就是额外比特的来源。

要回答您的最后一个问题,,如果y具有签名类型或比x窄,则使用x &= ~y来清除位是不安全的。有关这方面的更多信息,请参阅本文,但最重要的是,如果可能出现扩大的升级,请确保将~var转换为预期的unsigned类型。如果您使用uint8_t而不是auto作为z,您就不会遇到这个问题。