问题描述
我需要找到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;
可移植的方式是在 int
和 unsigned 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));
}