Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expression assigned to a wider essential type

Tags:

c

lint

misra

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?

like image 327
homeGrown Avatar asked Oct 24 '17 11:10

homeGrown


People also ask

What is essential type in C?

unsigned char is the essential type, and all typedef to unsigned char are completely compatible in C.

What is a composite expression 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.


2 Answers

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;
like image 93
Lundin Avatar answered Sep 28 '22 05:09

Lundin


This happens because 1U does not match uint32_t type. Use UINT32_C(...) macro to ensure type compatibility:

result = UINT32_C(1) << resolution;
like image 34
Sergey Kalinichenko Avatar answered Sep 28 '22 05:09

Sergey Kalinichenko