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?
unsigned char is the essential type, and all typedef to unsigned char are completely compatible in C.
Composite expressions are the means by which larger expressions are constructed from smaller expressions. This section describes the composite expressions except for functions, which we discuss in the following section. Some composite expressions impose restrictions on the possible types of their subexpressions.
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;
This happens because 1U
does not match uint32_t
type. Use UINT32_C(...)
macro to ensure type compatibility:
result = UINT32_C(1) << resolution;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With