简体   繁体   中英

MISRA C-2012 Rule 10.3 violation due to adding of two 8 bit variables which resulted in 32 bit

I am getting MISRA C-2012 Rule 10.3 violation: Implicit conversion of "var4 + var5" from essential type signed 32-bit int to different or narrower essential type unsigned 8-bit int" for the below code.

int8_t var4 = -10;
uint8_t var5 = 15;
uint8_t var6 = var4 + var5;

How "var4 + var5" is interpreted aa 32 bit int since each one are 8-bit size.

And also what is the correct way of fixing this ?

This happens due to integer promotions . This is detailed in section 6.3.1.1 of the C standard

2 The following may be used in an expression wherever an int or unsigned int may be used:

  • An object or expression with an integer type (other than int or unsigned int ) whose integer conversion rank is less than or equal to the rank of in t and unsigned int .
  • A bit-field of type _Bool , int , signed int , or unsigned int .

If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int ; otherwise, it is converted to an unsigned int . These are called the integer promotions. All other types are unchanged by the integer promotions.

Because an int8_t and uint8_t have lower rank than int , variables of these types are promoted to int when used in an expression. In the case of:

uint8_t var6 = var4 + var5;

Both var4 and var5 are promoted to int , and the result of the + operator is also of type int . That value is then assigned back to var6 , which is a uint8_t , which can result in truncation of the value.

The best way to handle this would be to first verify that the result cannot overflow, then explicitly cast the result:

uint8_t var6 = (uint8_t)(var4 + var5);

The reason why is implicit type promotions . There is 3 implicit promotions in that single line, which is dangerous and sloppy style. You have both integer promotion/usual arithmetic conversions and an implicit lvalue conversion in a single line of code.

You must understand how these coversions work in C, in order to write bug free C code, but you must also understand them in order to use MISRA-C. In fact, one of the purposes of MISRA-C has always been to educate programmers about implicit type promotions - you'll also find explanations in the MISRA-C document.

Your code actually violates several MISRA-C:2012 rules. Not only 10.3 which is concerned about the implicit lvalue conversions, but also 10.4:

Both operands of an operator in which the usual arithmetic conversions are performed shall have the same essential type category.

var4 is essentially signed and var5 is essentially unsigned. Therefore it is not enough to just cast the result to the appropriate type. To get MISRA-C compliant code you must cast both operands to the same type. Or better, use variables of appropriate type to begin with: it does not make much sense to store the result of -10 + 15 in an unsigned variable. Either you need signed numbers or you don't.

To get MISRA-C compliant code which is also fully portable, this should be a type that cannot get implicitly promoted, like uint32_t .

uint8_t var6 = (uint8_t) ((uint32_t)var4 + (uint32_t)var5);

alternatively

int8_t var6 = (int8_t) ((int32_t)var4 + (int32_t)var5);

This expression is rugged, professional C as it does not contain a single implicit promotion. It is self-documenting code, as it shows that the programmer knows about and has considered implicit type promotions. It does not affect performance compared to the expression with only 8 bit operands, since the compiler is free to optimize.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM