设置C中的最高有效位
我试图设置长无符号x中的最高有效位。 为此,我使用以下代码行:设置C中的最高有效位,c,bit-manipulation,C,Bit Manipulation,我试图设置长无符号x中的最高有效位。 为此,我使用以下代码行: x |= 1<<((sizeof(x)*8)-1); x |=1use 1all您正在移位的文本1不是自动的无符号长(而是int),因此没有您需要的位数。在其后缀上加上ULL(即1ULL),或在转换之前将其转换为无符号long,以使其成为正确的类型 另外,为了对奇怪的平台更安全,将8替换为CHAR\u bit。请注意,这仍然不一定是设置最高有效位的最佳方式,请参见,例如,有关备选方案 您还应该考虑使用一个类型,如“代码
x |= 1<<((sizeof(x)*8)-1);
x |=1use 1all您正在移位的文本1
不是自动的无符号长
(而是int
),因此没有您需要的位数。在其后缀上加上ULL
(即1ULL
),或在转换之前将其转换为无符号long
,以使其成为正确的类型
另外,为了对奇怪的平台更安全,将8
替换为CHAR\u bit
。请注意,这仍然不一定是设置最高有效位的最佳方式,请参见,例如,有关备选方案
您还应该考虑使用一个类型,如“代码> UTIN 64×T/<代码>,如果您假设“代码>未签名的长long < /代码>为某个宽度,或者<代码> UTIN FAST64 64 T < /代码> /<代码> UTITYLAST64 64 T < /代码>如果您需要至少一定宽度,或
uintmax\u t
,如果您需要最大的可用类型。正在移位的1
是int
类型的常量,这意味着您正在将int
值移位sizeof(无符号长)*8)-1
位。这种偏移很容易超过int
的宽度,这显然就是您的情况
如果您想要获得一些无符号长
类型的位掩码,您应该从无符号长
类型的初始位掩码开始,而不是int
类型的位掩码
1ull << (sizeof(x) * CHAR_BIT) - 1
或
由于2是负整数的补码表示,因此最负的整数正好是只设置了MSB的所需位模式。所以x |=(无符号长-长)长-长-分钟代码>也应该起作用。然后你还在做假设。如果你想便于携带,最好计算并设置msb。@这是的,sizeof(type)*CHAR_BIT
不是最好的解决方案,但至少它从OP的方法中删除了硬编码的8
。我喜欢这些新方法,尽管它们并不明显。投票给了一个好的答案,你还可以解释一下~(-1ull>>1)
或~(~0ull>>1)
是一种更好的方法吗?@rakeb.void因为它更紧凑,不依赖于字符位或其他常量,并且更易于读取(并且更小)。@rakeb.void:它“更好”因为它具有较少的冗余。原始变体在两个方面取决于目标类型:文字后缀ull
和移位距离sizeof(x)*字符位
。此替代方法只有一个依赖项-文字后缀。虽然乍一看不太明显,但程序员应该知道它是一种习惯用法。要避免依赖文字后缀,请使用正确整数类型的表达式:~((x | ~x)>>1)
或~(~(x^x)>>1)
,任何自尊心强的编译器都应该将这两个值进行常量折叠。(这只适用于x至少与int一样宽的情况,但我认为在这种情况下这不是问题。)不要使用幻数。C中的字节/char
可以有超过8位。用char\u位
替换8
。C实际上不保证2s补码,因此任何依赖于它的实现最多只能依赖于实现。整数不是“最有可能”的32位。有许多体系结构具有16位整数,有些具有24位整数,等等。(不过,你对UB的看法是正确的)。@Olaf:是的,我知道-int的大小不仅取决于体系结构,还取决于编译器。对于同一cpu,可以有两个编译器,并且具有不同的int大小。这里有许多细微差别。
1 << 63
1ull << (sizeof(x) * CHAR_BIT) - 1
~(-1ull >> 1)
~(~0ull >> 1)