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 The shift operators << and >> group left-to-right. The operands shall be of integral or unscoped enumeration type and integral promotions are performed.
我有模板函数
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 The shift operators << and >> group left-to-right. The operands shall be of integral or unscoped enumeration type and integral promotions are performed.