C++ 在相反方向上使用相同常量进行位移,对代码进行少量更改会产生不同的结果

C++ Bit Shift With Same Constant in Opposite Directions, Different Result With Minor Code Changes

我有模板函数

template< uint8_t HOW_FAR_CONSTANT, uint8_t START_CONSTANT, uint8_t ORIGINAL_CONSTANT>
uint8_t Foo();

Foo我做了这样的事情

const uint8_t OFFSET_CONSTANT = ( START_CONSTANT + HOW_FAR_CONSTANT );
const uint8_t RESULT_CONSTANT = ( ( ORIGINAL_CONSTANT << OFFSET_CONSTANT ) >> OFFSET_CONSTANT );

它不会截断位,结果是:

ORIGINAL: 10101010
RESULT: 10101010

但是,如果我稍微修改一下

const uint8_t OFFSET_CONSTANT = ( START_CONSTANT + HOW_FAR_CONSTANT );
const uint8_t RESULT_0_CONSTANT = ( ORIGINAL_CONSTANT << OFFSET_CONSTANT );
const uint8_t RESULT_CONSTANT = ( RESULT_0_CONSTANT >> OFFSET_CONSTANT );

我明白了

ORIGINAL: 10101010
RESULT 0 (lets say OFFSET_CONSTANT is 2): 10101000
RESULT: 00101010

我想知道这是否是一个糟糕的编译器优化。谁能解释一下?

更新:

在编译器资源管理器上试过这个,它绝对是标准行为,而且编译器优化也不错。

两者都没有优化。由于将移位操作的结果存储在 uint8_t.

类型的对象中,因此存在截断
const uint8_t RESULT_0_CONSTANT = ( ORIGINAL_CONSTANT << OFFSET_CONSTANT );

执行移位操作时,整数提升将应用于操作数。

所以在这个表达式中

const uint8_t RESULT_CONSTANT = ( ( ORIGINAL_CONSTANT << OFFSET_CONSTANT ) >> OFFSET_CONSTANT );
                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

子表达式 ( ORIGINAL_CONSTANT << OFFSET_CONSTANT ) 的类型为 int 而不是 uint8_t

来自 C++ 标准(5.8 移位运算符)

  1. 1 The shift operators << and >> group left-to-right. The operands shall be of integral or unscoped enumeration type and integral promotions are performed.