在C中设置最重要的位

时间:2015-07-05 18:10:51

标签: c bit-manipulation

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

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

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

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

4 个答案:

答案 0 :(得分:16)

您要转移的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)

答案 1 :(得分:7)

使用1ULL&lt;&lt;而不是1&lt;&lt;&lt;

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

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

将(最有可能):

1 << 63

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

答案 2 :(得分:1)

您正在移动的文字1不会自动为unsigned long long(而是int),因此没有您需要的位数。将其与ULL(即1ULL)后缀,或将其转换为unsigned long long,然后再转换为正确类型。

另外,为了让奇怪的平台更安全,请将8替换为CHAR_BIT。请注意,这仍然不一定是设置最高有效位的最佳方式,例如,请参阅this question替代方案。

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

答案 3 :(得分:-1)

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