如何在C中找到有符号整数的最高有效位

问题描述

我需要找到signed int N 的最高有效位并将其保存在signBitN 中。我想使用仅按位操作来做到这一点。 另外,我将如何使 signBitN 扩展,使其所有位都等于其有效位。 即如果它的有效位为零,我将如何将其扩展为 00000...00? 我得到的最接近的是 signBitN=1&(N>>(sizeof(int)-1));

解决方法

便携表达:

1 & (x >> (CHAR_BIT * sizeof(int) - 1))

最新的 C 标准有 3 个关于整数表示的标准。

  • 符号和大小
  • 一个补充
  • 两个补码 请参阅 C11 标准的 6.2.6.2 Integer types 部分。

只有第三个选项在实践中与现代机器相关。 如 6.2.6.1 中所述:

存储在任何其他对象类型的非位域对象中的值 由 n x CHAR_BIT 位组成,其中 n 是该类型对象的大小, 以字节为单位。

因此 int 将由 sizeof(int) * CHAR_BIT 位组成,可能为 32。 因此,可以通过右移 int 位并使用按位 sizeof(int) * CHAR_BIT - 1 运算符读取最后一位来读取 & 的最高位。

请注意,移位后 int 的确切值是实现定义的,如 6.5.7.5 中所述。

在正常机器上:

int y = x < 0 ? -1 : 0;

可移植的方式是在 intunsigned char 数组之间进行转换,并将所有字节设置为 -1。 见6.3.1.3.2

如果新类型是无符号的,则该值被转换为 重复加减一比最大值 可以在新类型中表示的值,直到值 在新类型的范围内。

还有6.2.6.1.2

存储在无符号位域和类型对象中的值 unsigned char 应使用纯二进制符号表示。

您可以使用 memset()

int x;
memset(&x,(x < 0 ? -1 : 0),sizeof x);
,

如果问题是如何检查整数的 MSB 位(例如 32 位整数的第 31 位)10 IMO,这是可移植的。

#define MSB(i)   ((i) & (((~0U) >> 1) ^ (~0U)))
#define issetMSB(i) (!!MSB(i))

int main(void)
{
    printf("%x\n",MSB(-1));
    printf("%x\n",issetMSB(-1));
}