2

When analysed by klocwork, the following line

pTxData[index] =  ( UINT8_C(0) << UINT8_C(4) );

gives error

Operand of bitwise operation has type 'signed char' instead of 'unsigned integer'

I already reduced the problem to the minimum by removing any #define and have absolutely no clue why this can happen.

Julien
  • 1,810
  • 1
  • 16
  • 34

2 Answers2

5

For those unaware, UINT8_C is a C standard macro1) for getting an integer constant of type uint_least8_t rather than the default int.

Thus UINT8_C(0) is equivalent to (uint_least8_t)0. This will be a small integer type. And as such it is subject to integer promotion2) when passed on as left operand to <<. After promotion it ends up as type int, equivalent to just writing 0.

You should never use signed operands with bitwise operators, so this is the core reason for the error message. Corrected code should look like 0u << 4. Although this code is of course pointless for anything except self-documenting code. (And of course shifting the value 0 is always harmless.)

Using UINT8_Con the right operand of << is nonsense - that operand does not partake in any type promotion of the result. If you need to use unsigned literals just to sate a coding standard, then use 4u. Notably, standards like MISRA-C do not require u suffix in cases where you actually don't need an unsigned type - this is a common source of false positives from tools.

Summary - use this:

pTxData[index] =  0u << 4;

In addition, Klockwork is giving an incorrect diagnostic message. The operators in your expression are both likely equivalent to unsigned char and definitely not signed char like the tool says.


1) Introduced in C99 7.18.4.1.

2) See Implicit type promotion rules

Lundin
  • 195,001
  • 40
  • 254
  • 396
1

In most expressions integer types of rank smaller than that of int get converted into int (if int can represent all values without a loss) or unsigned int (otherwise).

To simplify it a bit, consider the rank to correspond to the number of bits in the type, the more bits, the higher the rank (for a definitive treatment of the term, see a language reference (e.g. you may start here)).

And it seems to be the case here, the type returned by UINT8_C() (possibly unsigned char in disguise) has smaller rank than int and so you end up having a signed type.

Now, the reason for the warning is that shifting signed integer types is not well defined in all cases. Shifting negative values left or overflowing while shifting amounts to undefined behavior, meaning the program may misbehave in a wide variety of ways if either of those two conditions is encountered. (It's legal to overflow when shifting unsigned types, you get a truncated value).

Also, the shift count can't be negative.

However, if this is the exact code, the warning is unnecessary because it should be obvious that shifting 0 left by 4 positions is completely safe. If you used variables instead of constants, the compiler (or the tool) would not always be able to deduce safety of this shift and in that case you should pay attention to the warning and rewrite your code in such a way that there would be neither undefined behavior nor warning.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180