我想要在一个long long unsigned类型的变量x中设置最高位。 为了实现这个目标,我使用了下面这行代码:
x |= 1<<((sizeof(x)*8)-1);
我认为这应该可以工作,因为sizeof以字节为单位给出大小,所以乘以8并减去1可设置最终位。但每当我这样做时,编译器都会发出此警告:“warning: left shift count >= width of type”。
我不明白为什么会出现这个错误。
我想要在一个long long unsigned类型的变量x中设置最高位。 为了实现这个目标,我使用了下面这行代码:
x |= 1<<((sizeof(x)*8)-1);
我认为这应该可以工作,因为sizeof以字节为单位给出大小,所以乘以8并减去1可设置最终位。但每当我这样做时,编译器都会发出此警告:“warning: left shift count >= width of type”。
我不明白为什么会出现这个错误。
你正在移位的 1
是一个 int
类型的常量,这意味着你正在将一个 int
值左移 sizeof(unsigned long long) * 8) - 1
比特位。这种移位可能超过了 int
的宽度,这显然就是你遇到的问题。
如果你想获取 unsigned long long
类型的某个位掩码 mask,你应该从一个 unsigned long long
类型的初始位掩码开始,而不是从一个 int
类型开始。
1ull << (sizeof(x) * CHAR_BIT) - 1
构建同样的口罩可能有一种更好的方式是
~(-1ull >> 1)
或者~(~0ull >> 1)
~(-1ull >> 1)
或者 ~(~0ull >> 1)
是为什么更好呢? - mazhar islamCHAR_BIT
或其他常量,并且更易于阅读(和更小)。 - Filipe Gonçalvesull
和移位距离sizeof(x) * CHAR_BIT
。这种替代方法只有一个依赖关系-字面后缀。虽然乍一看不太明显,但程序员应该将其视为惯用法。 - AnT stands with Russia~((x|~x)>>1)
或 ~(~(x^x)>>1)
,这两个表达式应该被任何自重编译器进行常量折叠。 (仅当x至少与int一样宽时才有效,但我认为在这种情况下这不是问题。) - rici使用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
以使其成为正确的类型。8
替换为CHAR_BIT
。请注意,这仍然不一定是设置最高有效位的最佳方法,例如,可以参考this question中的其他方法。unsigned long long
是某个宽度,则还应该考虑使用uint64_t
等类型,如果你需要至少某个宽度,则应该使用uint_fast64_t
/uint_least64_t
,如果你需要最大可用类型,则应该使用uintmax_t
。sizeof(type) * CHAR_BIT
不是最佳解决方案,但至少它从OP的方法中删除了硬编码的8
。 - Arkkux |=(unsigned long long)LONG_LONG_MIN;
也应该有效。
char
可以有超过8位。请用CHAR_BIT
替换8
。 - too honest for this site