我想存储一个寄存器值,并执行如下所示的bitwise NOT operator
typedef union TEST_REG {
uint32_t u32Register;
uint8_t Byte[4];
uint16_t hword[2];
} tst_reg;
#define TEST_REGISTER ((volatile tst_reg*) 0x7023100CUL) // Register
下面是存储值的示例代码
#define CHECK_FLAG (0x00000004)
TEST_REGISTER->u32Register &= (uint32_t)(~(CHECK_FLAG));
但是当我执行TEST_REGISTER->u32Register &= (uint32_t)(~(CHECK_FLAG));
代码时,QAC
抛出一个警告,如
Constant: Negative value cast to an unsigned type
我明白如果我们做一个NOT (~) operator
,Hexa值将变为负数。
所以我想知道如何正确地将负值转换为无符号类型?有什么建议吗?
4条答案
按热度按时间neskvpey1#
但是当我执行
TEST_REGISTER->u32Register &= (uint32)(~(CHECK_FLAG));
代码时,QAC抛出一个警告,如首先,C不反对将负整数值转换为无符号类型。行为定义明确。反对的是MISRA。事实上,MISRA从根本上反对将
~
应用于有符号整数类型的表达式,* 并且 * 它反对将有符号整数类型的复合表达式转换为不同的“基本类型类别”,例如无符号整数。我不确定QAC的确切来源,但MISRA并不关心被转换的表达式的值是否实际上是负的。要做的事情是首先从一个无符号整数开始。您可以通过添加
u
或U
来实现这一点:0x00000004u
。或者,stdint.h
包含用于写入显式宽度类型常量的宏,通过使用其中适当的一个,您可以解决符号问题 * 和 * 避免强制转换:yvt65v4c2#
如何正确对待负价值..
使用掩码时,最好使用 unsigned 常量(这样就没有负值了)。
()
是不需要的,但也不是有害的。通常,cast 表示弱代码。
vuktfyat3#
在使用
~
运算符之前进行强制转换,或者通过强制转换将CHECK_FLAG定义为uint32,或者向文本添加“u”以指定它是无符号文本。或
查看此页面: www.example.com 中的不同后缀。
没有后缀的文字总是被解释为
int
。让我们来看看当你写的时候会发生什么:(uint32)(~(CHECK_FLAG))
CHECK_FLAG是文字
4
,因此在反转位时表现为有符号int,由于位反转而变为负值。(uint32)(-5)
现在,您将一个负值转换为无符号类型,编译器会警告您。
如果在反转之前将uint32强制转换为 *(或使用无符号文字开始),则反转不会导致负值,因为在反转位时变量已经是无符号的,并且无符号值不能变为负值。
nwlqm0z14#
您的MISRA检查器应该已经在
#define CHECK_FLAG (0x00000004)
处给予警告。这需要有一个U
/u
后缀才能兼容MISRA,这就是这里的实际问题。其他一些值得注意的事情:
0000....
除了使程序员感到困惑之外没有任何意义。当涉及到十六进制整数常量时,C是一种破碎的/厚脸皮的。假设32位系统,则0x00000004
的类型为int
,0x4
的类型为int
,但0x80000000
的类型为unsigned int
,0x100000000
的类型为long
或long long
。因此很容易编写细微的bug。作为一些RL轶事,我曾经接手过一个8位的16位
int
项目,他们习惯于像这样输入零,欺骗自己,以为他们得到的是32位数字。而事实上,该项目实际上包含了16位int
,16位unsigned int
和32位long
的混合,这是整个程序被破坏的主要原因之一。因此,正确的代码应该是:
在这种情况下,括号垃圾邮件对MISRA合规性没有影响-它只是膨胀,所以我删除了它。因为表达式的所有操作数都是无符号的,MISRA称之为“本质上是无符号的”,所以不再需要强制转换。