I' doing operation on bytes where I want to add an uint8 to the MSB of an existing uint32:

uint32 my_uint32;
my_uint32 = 0x00ffffffu;

my_uint32 = (uint32)(my_uint32) | ((uint8)(0x2u) << 24u));  // Add value 0x02 to the MSB of my_uint32 
my_uint32 = 0x02ffffffu    // This is what I get and is working so far

This is so far OK but I get the warning:

"An expression which is the result of a ~ or << operation has not been cast to its essential type"

I can get ride of the warning by doing:

my_uint32 = ((uint32)(my_uint32) | (uint8)((0x2u) << 24u)); // Here I'm doing the uint8 cast on the complete shift operation

But than this will not work. The result would be:

my_uint32 = 0x00ffffffu

Anyone idea how I can get away from the warning?

3

There are 3 best solutions below

2
On BEST ANSWER

Change my_uint32 = (uint32)(my_uint32) | ((uint8)(0x2u) << 24u)); to my_uint32 = my_uint32 | ((uint32) 0x2u << 24);.

Essentially, the left operand of a shift should be converted to the desired result type, so that the shift is performed with that type. Casting it to uint8 results in the shift being done with an int type, due to automatic promotion.

5
On

This should work:

my_uint32 = (uint32)(my_uint32) | (uint32)((uint32)(uint8)(0x2u) << 24u));

But it could be shortened to this:

my_uint32 = (uint32)(my_uint32) | (uint32)((uint32)(0x2u) << 24u));
0
On

What it means is that the operand (uint8)(0x2u) gets implicitly promoted to int, which is signed. Such promotions could cause subtle bugs.

Some old MISRA recommendation is to cast to the essential type afterwards, to ensure that the type of the expression stays consistent:

(uint32_t)(some_uint8_t << 24)

However, I would personally recommend to do this cast explicitly before the shift, so that you don't risk a type promotion to signed type then accidental shifts where you left shift bits into the sign bit or right shift with sign preserved (arithmetic shift) etc. That is, do this:

(uint32_t)some_uint8_t << 24

This is best practice on all 32 bit systems.


However, in your specific case the problem is here: (uint8)(0x2u).

2u is already of type unsigned int which is already the right type for bit shift by 24. (Unless it's a system with 16 bit int, in which case the cast to uint8 doesn't make any sense either.)

Just drop all the strange casts! This code is MISRA-C compliant:

my_uint32 = my_uint32 | (0x2u << 24u);

You only need to cast that operand if you need the code to work on 16 bit systems, in which case you can either do (uint32)0x2u or 0x2ul, either is fine and MISRA compliant.