为什么我的工具会在这里抛出 MISRA 错误?

发布于 2024-11-15 08:04:29 字数 263 浏览 2 评论 0原文

我该如何避免 MISRA 在以下代码中出现此错误?我尝试使用 (unit16_t) 进行铸造。但随后它不允许显式转换。

复杂表达式中从基础 MISRA 类型“unsigned char”到“unsigned int”的非法隐式转换(MISRA C 2004 规则 10.1)

 uint8_t rate = 3U; 
 uint8_t percentage = 130U;      
 uint16_t basic_units = rate * percentage;

What can I do to avoid MISRA giving this error for the code below? I tried casting with (unit16_t). But then it didn't allow an explicit conversion.

Illegal implicit conversion from underlying MISRA type "unsigned char" to "unsigned int" in complex expression (MISRA C 2004 rule 10.1)

 uint8_t rate = 3U; 
 uint8_t percentage = 130U;      
 uint16_t basic_units = rate * percentage;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

诗化ㄋ丶相逢 2024-11-22 08:04:29

问题是,比率和百分比都被整数提升为“int”类型而默默提升。因此,乘法是在有符号类型上执行的。

MISRA 兼容代码是重写代码

 uint16_t basic_units = (uint16_t)rate * (uint16_t)percentage;

或按照 MISRA 建议执行,立即将表达式的结果类型转换为其“底层类型”:

 uint16_t basic_units = (uint8_t)(rate * percentage);

编辑:澄清如下。

ISO 9899:1999 6.3.1.1 2

如果int可以表示原始类型的所有值,则将该值转换为int;
否则,它被转换为无符号整型。这些被称为整数
促销活动

来自 MISRA-C 的信息文本:

MISRA-C:2004 6.10.3 危险的类型转换:

/--/

- 算术运算中符号性的更改: 积分提升通常会导致两个无符号操作数产生 (signed) int 类型的结果。例如,如果 int 为 32 位,两个 16 位无符号操作数相加将产生有符号 32 位结果,但如果 int 为 16,则产生无符号 16 位结果位。

我实际上不确定上面的第二行是否满足 MISRA 的要求,再想一想,我可能将 MISRA 10.1 与 10.5 混淆了,后者强制立即转换为基础类型,但仅在某些按位运算符的情况下。

我用 LDRA 静态代码分析测试了这两行,它没有抱怨(但给出了一些不正确的、不相关的警告),但 LDRA 在 MISRA-C 上的表现也很差。

无论如何,原始问题中的问题是,比率和百分比都通过整数提升隐式转换为带符号的 int 类型,因为 int 可以表示 a 的所有值uint8_t。因此,

uint16_t basic units = (int)rate * (int)percentage.

为了防止这种情况,您必须显式进行类型转换。经过更多考虑后,我会选择上面两行中的第一行。

The problem is that both rate and percentage are silently promoted by the integer promotions to type "int". The multiplication is therefore performed on a signed type.

MISRA compatible code is to either rewrite the code as

 uint16_t basic_units = (uint16_t)rate * (uint16_t)percentage;

or do as MISRA suggests, immediately typecast the result of an expression to its "underlying type":

 uint16_t basic_units = (uint8_t)(rate * percentage);

EDIT: Clarification follows.

ISO 9899:1999 6.3.1.1 2

If an int can represent all values of the original type, the value is converted to an int;
otherwise, it is converted to an unsigned int. These are called the integer
promotions
.

Informative text from MISRA-C:

MISRA-C:2004 6.10.3 Dangerous type conversions:

/--/

- Change of signedness in arithmetic operations: Integral promotion will often result in two unsigned operands yielding a result of type (signed) int. For example, the addition of two 16-bit unsigned operands will yield a signed 32-bit result if int is 32 bits but an unsigned 16-bit result if int is 16 bits.

I'm actually not sure whether the 2nd line of mine above would satisfy MISRA or not, at second thought I may have confused MISRA 10.1 with 10.5, where the latter enforces an immediate cast to underlying type, but only in case of certain bitwise operators.

I tested both lines with LDRA static code analysis and it didn't complain (but gives some incorrect, non-related warnings), but then LDRA also performs very poorly at MISRA-C.

Anyway, the problem in the original question is that rate and percentage are both implicitly converted by the integer promotions to type int which is signed, since int can represent all values of a uint8_t. So it becomes

uint16_t basic units = (int)rate * (int)percentage.

To prevent this you have to typecast explicitly. After giving it more thought, I'd go with the 1st line of my two above.

三生路 2024-11-22 08:04:29

MISRA 规则试图确保用于计算的“基础类型”与结果类型相同。为此,您可以强制转换操作数中的一个或全部:

uint8_t rate = 3U; 
uint8_t percentage = 130U;      
uint16_t basic_units = (uint16_t)rate * percentage;

在 32 位体系结构上,不进行强制转换的结果是可以的,但是,请考虑以下事项:

uint32_t rate =  ...;
uint32_t percentage = ...;
uint64_t basic_units = rate * percentage;

在 32 位体系结构上,操作将在32 位 - 即使目标类型是 64 位宽。如果速率和百分比足够大,这可能会导致操作以 32 位封装,因此适合目标类型的数据将会丢失。

MISRA 规则试图使代码更安全,无论目标平台上的类型大小如何。

The MISRA rule is trying to ensure that the "underlying type" used for calculation is the same as the resulting type. To achieve that, you can cast the one, or both, of the operands:

uint8_t rate = 3U; 
uint8_t percentage = 130U;      
uint16_t basic_units = (uint16_t)rate * percentage;

On a 32-bit architecture the result without the cast is OK, however, consider the following:

uint32_t rate =  ...;
uint32_t percentage = ...;
uint64_t basic_units = rate * percentage;

On a 32-bit architecture, the operation will be performed in 32 bits - even though the target type is 64 bits wide. Where rate and percentage are large enough, this could result in the operation wrapping in 32 bits and so data that would have fit in the target type will be lost.

The MISRA rule is attempting to make the code safer irrespective of the size of the types on the target platform.

很酷又爱笑 2024-11-22 08:04:29

隐式转换在乘法之前执行,用于乘法。也许在乘法之前的显式转换会关闭您的工具

uint16_t basic_units = (unsigned)rate * (unsigned)percentage;

生成的无符号值应隐式转换为 uint16_t 且不会出现任何警告。如果您的工具也选择成为有关此问题的 PITA,请尝试另一种显式转换:

uint16_t basic_units = (uint16_t)((unsigned)rate * (unsigned)percentage);

The implicit conversion is performed before the multiplication, for the multiplication. Maybe an explicit conversion right before the multiplication shuts up your tool

uint16_t basic_units = (unsigned)rate * (unsigned)percentage;

The resulting unsigned value, should be implicitly converted to uint16_t with no warnings. If your tool chooses to be a PITA about this too, try another explicit conversion:

uint16_t basic_units = (uint16_t)((unsigned)rate * (unsigned)percentage);
夏の忆 2024-11-22 08:04:29

如果您尝试使用 C 风格转换来转换操作数,您可能会给您的工具带来其他一些抱怨。 ,而不是这样做:

uint16_t basic_units = (uint16_t)rate * (uint16_t)percentage;

因此,您可能需要这样做

uint16_t basic_units = static_cast<uint16_t>(rate) * static_cast<uint16_t>(percentage);

If you try casting your operands using C-style casting, you might just give your tool something else to complain about. So, instead of doing this:

uint16_t basic_units = (uint16_t)rate * (uint16_t)percentage;

You may need to do this:

uint16_t basic_units = static_cast<uint16_t>(rate) * static_cast<uint16_t>(percentage);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文