I have a template function
template< uint8_t HOW_FAR_CONSTANT, uint8_t START_CONSTANT, uint8_t ORIGINAL_CONSTANT>
uint8_t Foo();
In Foo
I do something like this
const uint8_t OFFSET_CONSTANT = ( START_CONSTANT + HOW_FAR_CONSTANT );
const uint8_t RESULT_CONSTANT = ( ( ORIGINAL_CONSTANT << OFFSET_CONSTANT ) >> OFFSET_CONSTANT );
And it does not truncate the bits, it results in:
ORIGINAL: 10101010
RESULT: 10101010
However, if I make a slight modification
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 );
I get
ORIGINAL: 10101010
RESULT 0 (lets say OFFSET_CONSTANT is 2): 10101000
RESULT: 00101010
I am wondering if this is a bad compiler optimization. Can anyone explain this?
UPDATE:
Tried this on compiler explorer, its definitely standard behavior and not a bad compiler optimization.
There is neither optimization. There is a truncation due to storing a result of a shift operation in an object of the type uint8_t
.
const uint8_t RESULT_0_CONSTANT = ( ORIGINAL_CONSTANT << OFFSET_CONSTANT );
When the shift operation is performed the integral promotions are applied to operands.
So in this expression
const uint8_t RESULT_CONSTANT = ( ( ORIGINAL_CONSTANT << OFFSET_CONSTANT ) >> OFFSET_CONSTANT );
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
the sub-expression ( ORIGINAL_CONSTANT << OFFSET_CONSTANT )
has the type int
instead of uint8_t
.
From the C++ Standard (5.8 Shift operators)
- 1 The shift operators << and >> group left-to-right. The operands shall be of integral or unscoped enumeration type and integral promotions are performed.