### 问题

My static analyzer is throwing the following warning:

MCPP Rule 5-0-3: This complex expression is implicitly converted to a different essential type

for the following code:

```
void func(const uint32_t arg)
{
//32U has underlying type uint8_t
const uint32_t u32a = arg % 32U; //warning issued in this line
const uint32_t u32b = (arg % static_cast<uint32_t>(32U)); //same warning issued in this line
const uint32_t u32c = static_cast<uint32_t>(arg % 32U); //compliant
}
```

According to MISRA underlying type conversion rules:

Otherwise, if both operands have integral type, the underlying type of the expression can be found using the following:

– If the types of the operands are the same size, and either is unsigned, the result is unsigned.

– Otherwise, the type of the result is that of the larger type.

I think this warning may be a false positive because, despite the `32U`

being a `uint8_t`

, the expression should take the underlying type of the larger type, in this case the `uint32_t`

, thus making the need for the `static_cast`

unnecessary.

Do you agree this is a false positive? Or am I looking at it all wrong?

EDIT: The MISRA standard states that:

The underlying type of an integer constant expression is therefore defined as follows:

If the actual type of the expression is signed integral, the underlying type is defined as the smallest signed integer type that is capable of representing its value.

If the actual type of the expression is unsigned integral, the underlying type is defined as the

smallestunsigned integer type that is capable of representing its value.In all other circumstances, the underlying type of the expression is defined as being the same as its actual type.

No. 2 is the reason why I've to assume that `32U`

has the underlying type of `uint8_t`

.

### 回答1:

You have found the relevant section. The type of the expression where the literal is located is unsigned, so the *underlying type* is the smallest one that can fit an unsigned value `32`

, meaning `uint8_t`

. It would have the very same underlying type if the literal had been `32`

without the U suffix (though that would violate other MISRA rules).

What MISRA is aiming for here is that in the specific expression `uint32_t arg; ... arg % 32U`

there can never occur a dangerous implicit conversion. That being said, you can safely cast the literal to `uint32_t`

and that should silence all warnings. Ensuring that there are no implicit type promotions in your code what-so-ever is good programming practice, no matter what MISRA says/doesn't say.

If the purpose of the static analyser is just to check for implicit promotions in general, then the warning is fine. If the purpose of your static analyser is to check for MISRA compliance, then it is a false positive.

The line `arg % static_cast<uint32_t>(32U)`

should never yield any form of diagnostic, regardless of the purpose of the tool. That is certainly a false positive.

### 回答2:

I think this warning may be a false positive because, despite the

`32U`

being a`uint8_t`

`32U`

is not a `uint8_t`

on any platform. With integer literals the smallest type you can express is a `int`

/`unsigned int`

. According to cppreference `nnnnU`

can be
a `unsigned int`

, `unsigned long int`

, or `unsigned long long int`

. It does pick the first type that the literal can be stored in so `32U`

is a `unsigned int`

.

So if you want to guarantee that `32U`

is the same type as `uint32_t`

then you need the cast on the right hand side.

### 回答3:

`32U`

is of type `unsigned`

, which is potentially a distinct type from `uint32_t`

. Contrary to your statement, it is never of type `uint8_t`

A `unsigned`

is only guaranteed to be able to represent the values in the range `0`

to `65535`

, although it is permitted to support a larger range. What it actually can represent is implementation-defined. However, it cannot be a `uint8_t`

, since a `uint8_t`

cannot represent the range required of an `unsigned`

.

This means, practically, three possibilities are that `unsigned`

may be a 16-bit type, a 32-bit type, or even a 64-bit type - and these are, respectively, smaller, the same size, or larger than a `uint32_t`

.

The result of the expression `arg % 32U`

may therefore be of type `uint32_t`

(if `unsigned`

is 16-bit), `uint32_t`

(if `unsigned`

and `uint32_t`

are both the same 32-bit type), or `unsigned`

(if `unsigned`

is a 64-bit type). In the last case, a conversion from `unsigned`

to `uint32_t`

is required to initialise `u32a`

.

Your static analyser is warning you of this potential variation of behaviours between systems.

So, no, it is not a false positive.

来源：`https://stackoverflow.com/questions/43206493/misra-c-rule-5-0-3-false-positive-warning`