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
orunsigned int
may be used:
- An object or expression with an integer type (other than
int
orunsigned int
) whose integer conversion rank is less than or equal to the rank ofin
t andunsigned int
.- A bit-field of type
_Bool
,int
,signed int
, orunsigned 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 anint
; otherwise, it is converted to anunsigned 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.