I get the following warning from our analysis tool Composite expression assigned to a wider essential type
This is the code:
uint32_t result;
uint8_t resolution;
result = 1U << resolution;
I tried the following:
#define SHIFT_BY_ONE (uint8_t)1
result = SHIFT_BY_ONE << resolution;
but that then throws this warning Shift left of signed quantity (int)
so I guess I am not understanding the issue correctly. How do I fix this error?
This sounds as if you are running a MISRA-C:2012 checker. Essential type and composite expression are terms from MISRA-C, not from the C standard.
In order to understand anything at all from this warning, you have to study the meaning of essential type (MISRA-C:2012 8.10) and composite expression (MISRA-C:2012 8.10.3).
As for the reason for the warning, it is rule 10.6:
The value of a composite expression shall not be assigned to an object with wider essential type.
If we ignore the meaning of all these terms, what the rule boils down to is that if you have an operation with 2 operands of a smaller type, the result should not get assigned to a variable of larger type than those operands.
This is to prevent code like this:
uint16_t a = 40000;
uint16_t b = 40000;
uint32_t result = a + b;
On a 16 bit system, the operands a
and b
will not get promoted, so the actual operation will get carried out on 16 bit type - and there will be an unsigned wrap-around (or overflow in case of signed variables).
Confused programmers that don't understand how implicit type promotions work in C might think that the above operation gets carried out on uint32_t
just because the result is stored in such a type. But this is not correct, the left-hand side of the assignment operator has nothing to do with the sub-expression a + b
what-so-ever. Which type that gets used in sub-expressions is entirely determined by operator precedence, and =
has lower precedence than +
.
Apparently MISRA-C believes that such misunderstandings are common, which is the rationale for this rule.
As for how to fix it, it is easy:
result = (uint32_t)1U << resolution;