在C中设置最重要的位

我试图在长的无符号x中设置最重要的位。 要做到这一点,我使用这行代码:

x |= 1<<((sizeof(x)*8)-1); 

我认为这应该工作,因为sizeof以字节为单位给出大小,所以我乘以8并减去1来设置最后一位。 每当我这样做时,编译器都会出现此警告:“警告:左移计数> =类型的宽度”

我不明白为什么会出现这种错误。

您正在移位的1int类型的常量,这意味着您将int值移位sizeof(unsigned long long) * 8) - 1位。 这种转变很容易超过int的宽度,这显然就是你的情况。

如果要获得一些unsigned long long类型的位掩码掩码,则应该使用unsigned long long类型的初始位掩码,而不是int类型。

 1ull << (sizeof(x) * CHAR_BIT) - 1 

构建相同掩模的一种可以说是更好的方法

 ~(-1ull >> 1) 

要么

 ~(~0ull >> 1) 

使用1ULL <<而不是1 <<

仅使用“1”可以移动整数。 1ULL将是一个无符号长的长,这是你需要的。 整数可能是32位, long long整数可能是64位宽。 所以转移:

 1 << ((sizeof(long long)*8)-1) 

将(最有可能):

 1 << 63 

由于1是(最可能)32位的整数,因此您会收到警告,因为您试图移过32位值的MSB。

你正在移动的文字1不是自动的unsigned long long (但是int ),因此没有你需要的那么多位。 使用ULL (即1ULL )后缀,或者在移位前将其转换为unsigned long long 1ULL ,以使其成为正确的类型。

另外,为了让奇怪的平台更安全一点,用CHAR_BIT替换8 。 请注意,这仍然不一定是设置最重要位的最佳方式,例如,请参阅此问题以寻找替代方案。

如果您假设unsigned long long为某个宽度,则还应考虑使用uint64_t这样的类型uint_least64_t如果需要至少一定宽度,则应考虑使用uint_fast64_t / uint_least64_t如果需要最大可用类型, uintmax_t

由于负整数的2的补码表示,最负的整数正是所需的位模式,只有MSB集。 所以x |= (unsigned long long )LONG_LONG_MIN; 也应该工作。