关于 Microsoft C++ 中按位移位的问题

Question about Bitwise Shift in Microsoft C++

我正在 Microsoft C++ 中进行以下位移:

uint8_t arr[3] = {255, 255, 255};
uint8_t value = (arr[1] << 4) >> 4;

这些操作的结果让我很困惑:

value = 255

但是,如果我单独进行位移:

value = (arr[i] << 4);
value = value >> 4;

答案不同而且很有道理:

value = 15

有人可以向我解释为什么会这样吗?我熟悉移位的概念,所以我相信...

提前致谢!

(P.S.: 似乎 g++ 会有相同的行为。我可能遗漏了一些重要的位移概念。非常感谢任何帮助!)

在这个带有移位运算符的表达式中

(arr[1] << 4) >> 4;

使用了积分促销。也就是说,操作数 arr[1] 被提升为类型 int 的对象,这样的对象可以存储表达式 arr[i] << 4.

的结果

来自 C++ 14 标准(5.8 移位运算符,第 #1 页)

...The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

这里有一个演示程序

#include <iostream>
#include <iomanip>
#include <type_traits>
#include <cstdint>

int main()
{
    uint8_t x = 255;

    std::cout << "std::is_same_v<decltype( x << 4 ), int> is "
              << std::boolalpha
              << std::is_same_v<decltype( x << 4 ), int> << '\n';

    std::cout << "x << 4 = " << ( x << 4 ) << '\n';
}

程序输出为

std::is_same_v<decltype( x << 4 ), int> is true
x << 4 = 4080

至于这段代码

value = (arr[i] << 4);
value = value >> 4;

那么在第一个赋值语句中,移位操作的结果被截断了。

表达式 (arr[1] << 4) 将在应用移位操作之前隐式地将 arr[1] 的值提升为类型 unsigned int,这样“中间”结果就不会“丢失”任何位( cf,例如implicit conversions).

中的解释

然而,当你写 value = (arr[i] << 4); 时,这个“中间”结果将被转换回 uint_8,并且在这一步中位被截断。

写的时候看看区别uint8_t value = ((uint8_t)(arr[1] << 4)) >> 4;