我正在使用带有MISRA :2004的编译器。
碎片是:
#define UNS_32 unsigned int
UNS_32 arg = 3U;
UNS_32 converted_arg = (UNS_32) arg;
/* Error line --> */ UNS_32 irq_source = (UNS_32)(1U << converted_arg);MISRA错误是: ErrorPm136:从底层MISRA类型"unsigned“到"unsigned”的非法显式转换(MISRA 2004规则10.3)
我在上面的代码中没有看到任何unsigned char。
Why did Misra throw an error here?的讨论讨论了乘法,它可能有不同的促进规则,而不是左移。
我的理解是,编译器应该将表达式提升到较大的数据类型,而不是降级到更小的大小。
这到底是怎么回事?
如何使代码MISRA C:2004兼容?
编辑1:
将错误行更改为:
UNS_32 irq_source = (UNS_32)((UNS_32) 1U << converted_arg); 不是让错误消失了吗?
发布于 2012-02-06 10:24:10
第二个问题:
如何使代码MISRA :2004兼容?
您可以以符合MISRA的方式编写它,如下所示:
typedef unsigned int UNS_32;
UNS_32 test(void);
UNS_32 test(void)
{
UNS_32 original_arg = 3U;
UNS_32 irq_source = 1UL << original_arg;
return irq_source;
}回到第一个问题:
这里到底发生了什么?
第一条规则10.3规定,复杂整数表达式不应转换为比基础类型更宽的类型。
理解错误消息的一个关键是基本类型的概念,这是一个特定于MISRA-C的概念。简而言之,常数的底层类型是它可以容纳的最小类型。在本例中,1U具有底层类型unsigned char,尽管它具有语言类型unsigned int。
10.3规则的基本原理是避免在比部分更大的上下文中使用操作的结果。这方面的标准示例是乘法,其中alpha和beta是16位类型:
uint32_t res = alpha * beta;这里,如果int是16位,则乘法将以16位执行,然后将结果转换为32位。另一方面,如果int为32位或更大,则将以更高的精度执行乘法。具体而言,这将使结果在乘以0x4000和0x10时有所不同。
MISRA规则10.3解决了这一问题,强制将强制结果放置在一个临时的位置,然后将其转换为更大的类型。这样,您就不得不以某种方式编写代码。
如果目的是使用16位乘法:
uint16_t tmp = alpha * beta;
uint32_t res = tmp;另一方面,如果目的是32位乘法:
UNS_32 res = (UNS_32)alpha * (UNS_32)beta;因此,在这种情况下,表达式1U << count是潜在的问题。如果converted_arg大于16位,这可能会导致使用16位ints. MISRA允许您编写1UL << count或(UNS_32)((UNS_32)1U << original_arg)时出现问题。你提到米斯拉检查器在后一种情况下发出了一个错误-请再次检查。
所以,在我看来,你使用的MISRA C检查器正确地识别了违反规则10.3的行为。
发布于 2012-02-04 04:29:22
在米斯拉规则指定的C89中,以U后缀的整数常量的类型是列表“无符号int,无符号长int”中的第一个,其中可以表示其值。这意味着1U的类型必须是unsigned int。
按位移位运算符的定义指定对每个操作数执行整数提升(这不会改变unsigned int),并且结果的类型是提升的左操作数的类型。因此,在这种情况下,(1U << converted_arg)的结果类型是unsigned int。
这里唯一的显式转换是将此unsigned int值转换为unsigned int,所以这必须是编译器所警告的--尽管看不到unsigned char,这意味着检查器似乎是错误的。
但从技术上讲,从unsigned int到unsigned int的转换似乎违反了规则10.3,该规则规定,“复杂表达式”的结果只能转换为较窄的类型,而转换到相同类型的结果显然不能转换为较窄的类型。
演员阵容是没有必要的--我只想省略一下。
发布于 2018-10-18 20:25:31
在MISRA的早期,应用它的程序有时会针对那些行为不符合尚未发布的C89标准的编译器。在发明C的机器上,对16位值的操作与对8位值的操作所花费的费用相同。将char值提升到int,并在存储回char时截断结果实际上比直接对char值执行算术更便宜和容易。C标准一旦发布,就会要求所有C实现必须将所有整数值提升为至少可以容纳范围-32767.32767的int类型,或者至少可以容纳0..65535的unsigned类型,或者更大的类型,以8位计算机为目标的1980年代编译器并不总是这样做的。
虽然现在尝试使用不能满足这些要求的C编译器似乎很疯狂,但是80年代的程序员通常会面临着在使用"C-ish“编译器还是用汇编语言编写所有东西之间的选择。MISRA中的一些规则,包括“固有类型”规则,旨在确保程序即使在将int视为8位类型的奇怪实现上运行也是有效的。
https://stackoverflow.com/questions/9137737
复制相似问题