Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Rule 10.5
#1
First of all, in the explaining text to Chapter 6.10 you can read the following below \"Balancing conversions\":

\"Notice that the operands of the bitwise shift operators (>) are not balanced. The type of the result is the promoted type of the first operand.\"

The balancing refers to the \"usual arithmetic conversions\" and I believe that the text is correct.

Then in the example for rule 10.5 the following code is posted:

Code:
uint8_t port = 0x5aU;
uint8_t result_8;
uint16_t result_16;

result_8 = (~port) >> 4;  /* not compliant */
...
result_8 = ((uint8_t)(~port)) >> 4; /* compliant */
result_16 = ((uint16_t)(~(uint16_t)port)) >> 4; /* compliant */

The last line with result_16 is incorrect and not compliant to rule 10.5 nor rule 10.3. The result of that line will be 0x0FFA and not 0x000A.

The rule 10.5 states that the result of an expression shall be immediately cast to the underlying type. Underlying type is defined as the type an expression would have if not for the integer promotions. If not for the integer promotions, the type of the expression (~port) would be uint8_t and the type of the expression (~port) >> 4 would be also be uint8_t, since the usual arithmetic conversions aren't used, see the text on top of this post.

First error in that line:

~(uint16_t)port

The operand is casted instead of the result.

Second error on that line:
The result is not casted to the underlying type which is uint8_t.

Third error on that line:
result_16 = (uint16_t) ...

The result is not casted to the underlying type of the expression
\"uint8_t result\" >> 4
which is uint8, since the usual arithmetic conversions aren't used on shift operators.

So not only does the line break rule 10.5, it also breaks rule 10.3 in MISRA C:2004 TC1: \"The value of a complex expression of integer type shall only be cast to a type of the same signedness that is no wider than the underlying type of the expression\".

I believe that the correct line will look like this:

Code:
result_16 = (uint8_t) ( ((uint8_t)~port) >> 4U ); /* compliant */
However, that line looks quite horrible. I suggest that the following code is used instead:

Code:
result_8  = (uint8_t) ~port;
result_16 = (uint8_t) (result_8 >> 4U);


Messages In This Thread

Forum Jump:


Users browsing this thread: 3 Guest(s)