【问题标题】:Setting the Most significant sign bit(Lint warning)设置最高有效符号位(Lint 警告)
【发布时间】:2017-07-21 09:39:04
【问题描述】:

我正在处理一个函数,我必须转换一个 3 字节数组并将 3 字节数组作为单个 int32 返回。 代码如下: pbData 是指向字节数组的指针。

const byte bMSBitPosNeg = 0x80;
const byte bMSBNeg = 0xFF;
int32 i32Num = 0;

//Big - Endian
if (pbData != NULL)
{
    if ((pbData[0] & bMSBitPosNeg) == bMSBitPosNeg) //Negative
    {
        i32Num |= (bMSBNeg * 0x1000000); //Force MSB to 0xFF as 3 bytes are 
                                        //converted to 4 bytes
    }

    i32Num |= (pbData[0] << 16);
    i32Num |= (pbData[1] << 8);
    i32Num |= (pbData[2]);

}
return i32Num;

输入:{0x00,0xBB,0xA3} 输出:48035 //正数

输入:{0xff,0x44,0x5d} 输出:-48035 //负数

代码按预期工作,但我收到一个 lint 警告。 警告 648:运算常数计算溢出:“乘法”

我需要该功能但不想要警告。如何抑制它?

【问题讨论】:

  • 0x1000000 常量上使用 UL 后缀
  • 如果你把乘法作为对应的移位,那有意义吗?请记住,您使用的是 int,它是一个 signed 32 位类型(在大多数平台上)。
  • 一般提示:使用位时,始终使用显式无符号数据类型。
  • @Someprogrammerdude 在这种情况下,在某些情况下希望返回负值,所以这并不简单
  • @M.M 我仍然建议使用无符号类型进行实际的位处理,然后在需要时将其转换为有符号类型。

标签: c lint


【解决方案1】:

您可以用位移代替乘法,甚至可以手动计算位模式以获得更好的可读性:

const int32 bMSBNeg = (int32)0xFF000000;

您还可以通过在高三个字节中构造数字,然后通过除法将其向下移动 8 位来避免所有这些计算:

if (pbData != NULL) {
    i32Num = ((pbData[0] << 24) | (pbData[1] << 16) | (pbData[2] << 8)) / 256;
}

注意:移动 8 而不是除以 256 将是根据标准实现定义的行为。

【讨论】:

  • 您的第一行是一个超出范围的赋值(这里在解包负值时存在一些问题;如果 OP 想要避免实现定义的行为,那么我们将不得不小心)
  • C11 标准草案 n1570:6.5.7 位移位运算符 5 E1 >> E2 的结果是 E1 右移 E2 位位置。 [...] 如果 E1 具有带符号类型和负值,则结果值是实现定义的。
  • @EOF 糟糕,令人讨厌的标准及其实现定义的行为再次吸引了我。我应该使用除以 256。
  • 我认为像“理智的实现”这样的警告已经足够好了,但你的解决方案更好。
  • @EOF 是的,OP 的整个方法都依赖于“合理的实现”——即使在高字节中设置 FF 也依赖于二进制补码表示。它会在符号和幅度平台上崩溃(这些天几乎完全是虚构的,但标准作家必须假装它们存在)。
猜你喜欢
  • 1970-01-01
  • 2015-09-22
  • 2017-07-31
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-23
  • 2010-11-11
相关资源
最近更新 更多