警告:"An expression which is the result of a ~ or << operation has not been cast to its essential type" - 如何修复?
Warning: "An expression which is the result of a ~ or << operation has not been cast to its essential type" - How to fix?
我正在对字节进行操作,我想将 uint8 添加到现有 uint32 的 MSB 中:
uint32 my_uint32;
my_uint32 = 0x00ffffffu;
my_uint32 = (uint32)(my_uint32) | ((uint8)(0x2u) << 24u)); // Add value 0x02 to the MSB of my_uint32
my_uint32 = 0x02ffffffu // This is what I get and is working so far
到目前为止一切正常,但我收到警告:
"作为 ~ 或 << 操作结果的表达式尚未转换为其基本类型"
我可以通过以下方式摆脱警告:
my_uint32 = ((uint32)(my_uint32) | (uint8)((0x2u) << 24u)); // Here I'm doing the uint8 cast on the complete shift operation
但这行不通。结果将是:
my_uint32 = 0x00ffffffu
有人知道我怎样才能摆脱警告吗?
这应该有效:
my_uint32 = (uint32)(my_uint32) | (uint32)((uint32)(uint8)(0x2u) << 24u));
但可以缩短为:
my_uint32 = (uint32)(my_uint32) | (uint32)((uint32)(0x2u) << 24u));
将 my_uint32 = (uint32)(my_uint32) | ((uint8)(0x2u) << 24u));
更改为 my_uint32 = my_uint32 | ((uint32) 0x2u << 24);
。
本质上,应该将移位的左操作数转换为所需的结果类型,以便使用该类型执行移位。由于自动升级,将其转换为 uint8
会导致使用 int
类型完成转换。
这意味着操作数 (uint8)(0x2u)
被隐式提升为 int
,这是有符号的。此类促销活动可能会导致细微的错误。
一些旧的 MISRA 建议是之后转换为基本类型,以确保表达式的类型保持一致:
(uint32_t)(some_uint8_t << 24)
但是,我个人建议在 转换之前 明确地执行此转换,这样您就不会冒将类型提升为签名类型然后意外转换到您离开的位置的风险位进入符号位或右移并保留符号(算术移位)等。也就是说,这样做:
(uint32_t)some_uint8_t << 24
这是所有 32 位系统上的最佳做法。
但是,在您的具体情况下,问题出在这里:(uint8)(0x2u)
.
2u
已经是 unsigned int
类型,它已经是 24 位移位的正确类型。(除非它是具有 16 位 int
的系统,在这种情况下,强制转换uint8
也没有任何意义。)
扔掉所有奇怪的施法!此代码符合 MISRA-C 标准:
my_uint32 = my_uint32 | (0x2u << 24u);
如果您需要代码在 16 位系统上工作,您 仅 需要转换该操作数,在这种情况下,您可以执行 (uint32)0x2u
或 0x2ul
,两者都可以,并且符合 MISRA 标准。
我正在对字节进行操作,我想将 uint8 添加到现有 uint32 的 MSB 中:
uint32 my_uint32;
my_uint32 = 0x00ffffffu;
my_uint32 = (uint32)(my_uint32) | ((uint8)(0x2u) << 24u)); // Add value 0x02 to the MSB of my_uint32
my_uint32 = 0x02ffffffu // This is what I get and is working so far
到目前为止一切正常,但我收到警告:
"作为 ~ 或 << 操作结果的表达式尚未转换为其基本类型"
我可以通过以下方式摆脱警告:
my_uint32 = ((uint32)(my_uint32) | (uint8)((0x2u) << 24u)); // Here I'm doing the uint8 cast on the complete shift operation
但这行不通。结果将是:
my_uint32 = 0x00ffffffu
有人知道我怎样才能摆脱警告吗?
这应该有效:
my_uint32 = (uint32)(my_uint32) | (uint32)((uint32)(uint8)(0x2u) << 24u));
但可以缩短为:
my_uint32 = (uint32)(my_uint32) | (uint32)((uint32)(0x2u) << 24u));
将 my_uint32 = (uint32)(my_uint32) | ((uint8)(0x2u) << 24u));
更改为 my_uint32 = my_uint32 | ((uint32) 0x2u << 24);
。
本质上,应该将移位的左操作数转换为所需的结果类型,以便使用该类型执行移位。由于自动升级,将其转换为 uint8
会导致使用 int
类型完成转换。
这意味着操作数 (uint8)(0x2u)
被隐式提升为 int
,这是有符号的。此类促销活动可能会导致细微的错误。
一些旧的 MISRA 建议是之后转换为基本类型,以确保表达式的类型保持一致:
(uint32_t)(some_uint8_t << 24)
但是,我个人建议在 转换之前 明确地执行此转换,这样您就不会冒将类型提升为签名类型然后意外转换到您离开的位置的风险位进入符号位或右移并保留符号(算术移位)等。也就是说,这样做:
(uint32_t)some_uint8_t << 24
这是所有 32 位系统上的最佳做法。
但是,在您的具体情况下,问题出在这里:(uint8)(0x2u)
.
2u
已经是 unsigned int
类型,它已经是 24 位移位的正确类型。(除非它是具有 16 位 int
的系统,在这种情况下,强制转换uint8
也没有任何意义。)
扔掉所有奇怪的施法!此代码符合 MISRA-C 标准:
my_uint32 = my_uint32 | (0x2u << 24u);
如果您需要代码在 16 位系统上工作,您 仅 需要转换该操作数,在这种情况下,您可以执行 (uint32)0x2u
或 0x2ul
,两者都可以,并且符合 MISRA 标准。