在 C 中设置最高有效位

set most significant bit in C

我正在尝试设置 long long unsigned x 中的最高有效位。 为此,我使用了这行代码:

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

我认为这应该可行,因为 sizeof 以字节为单位给出大小,所以我乘以 8 并减去 1 来设置最后一位。每当我这样做时,编译器都会发出警告:"warning: left shift count >= width of type"

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

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

仅使用“1”就可以移动一个整数。 1ULL 将是一个 unsigned long long,这正是您所需要的。 整数可能是 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 以使其成为正确的类型。

此外,为了让陌生平台更安全一些,请将 8 替换为 CHAR_BIT。请注意,这仍然不一定是设置最高有效位的最佳方法,例如,参见 this question 了解替代方案。

如果您假设 unsigned long long 具有特定宽度,您还应该考虑使用 uint64_t 等类型,或者如果您需要 uint_fast64_t/uint_least64_t至少一定的宽度,或者 uintmax_t 如果你需要最大的可用类型。

您正在移动的 1 是一个 int 类型的常量,这意味着您正在将 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)

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