简体   繁体   English

在C中设置最重要的位

[英]set most significant bit in C

I am trying to set the most significant bit in a long long unsigned, x. 我试图在长的无符号x中设置最重要的位。 To do that I am using this line of code: 要做到这一点,我使用这行代码:

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

I thought this should work, because sizeof gives size in bytes, so I multiplied by 8 and subtract one to set the final bit. 我认为这应该工作,因为sizeof以字节为单位给出大小,所以我乘以8并减去1来设置最后一位。 Whenever I do that, the compiler has this warning: "warning: left shift count >= width of type" 每当我这样做时,编译器都会出现此警告:“警告:左移计数> =类型的宽度”

I don't understand why this error is occurring. 我不明白为什么会出现这种错误。

The 1 that you are shifting is a constant of type int , which means that you are shifting an int value by sizeof(unsigned long long) * 8) - 1 bits. 您正在移位的1int类型的常量,这意味着您将int值移位sizeof(unsigned long long) * 8) - 1位。 This shift can easily be more than the width of int , which is apparently what happened in your case. 这种转变很容易超过int的宽度,这显然就是你的情况。

If you want to obtain some bit-mask mask of unsigned long long type, you should start with an initial bit-mask of unsigned long long type, not of int type. 如果你想获得的一些位掩码掩码unsigned long long类型,你应该用的初始位掩码开始unsigned long long类型不是, int类型。

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

An arguably better way to build the same mask would be 构建相同掩模的一种可以说是更好的方法

~(-1ull >> 1)

or 要么

~(~0ull >> 1)

use 1ULL << instead of 1 << 使用1ULL <<而不是1 <<

Using just "1" makes you shift an integer. 仅使用“1”可以移动整数。 1ULL will be an unsigned long long which is what you need. 1ULL将是一个无符号长的长,这是你需要的。 An integer will probably be 32 bits and long long probably 64 bits wide. 整数可能是32位, long long整数可能是64位宽。 So shifting: 如此转变:

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

will be (most probably): 将(最有可能):

1 << 63

Since 1 is an integer which is (most probably) 32 bits you get a warning because you are trying to shift past the MSB of a 32 bit value. 由于1是一个整数(最可能)是32位,因此您会收到警告,因为您试图移过32位值的MSB。

The literal 1 you are shifting is not automatically an unsigned long long (but an int ) and thus does not have as many bits as you need. 你正在移动的文字1不是自动的unsigned long long (但是int ),因此没有你需要的那么多位。 Suffix it with ULL (ie, 1ULL ), or cast it to unsigned long long before shifting to make it the correct type. 使用ULL (即1ULL )对其进行后缀,或者在移位之前将其转换为unsigned long long 1ULL ,以使其成为正确的类型。

Also, to be a bit safer for strange platforms, replace 8 with CHAR_BIT . 另外,为了让奇怪的平台更安全一点,用CHAR_BIT替换8 Note that this is still not necessarily the best way to set the most significant bit, see, eg, this question for alternatives. 请注意,这仍然不一定是设置最重要位的最佳方式,例如,请参阅此问题以寻找替代方案。

You should also consider using a type such as uint64_t if you're assuming unsigned long long to be a certain width, or uint_fast64_t / uint_least64_t if you need at least a certain width, or uintmax_t if you need the largest available type. 如果您假设unsigned long long为某个宽度,则还应考虑使用uint64_t这样的类型uint_least64_t如果需要至少一定宽度,则应考虑使用uint_fast64_t / uint_least64_t如果需要最大可用类型, uintmax_t

Thanks to the 2's complement representation of negative integers, the most-negative interger is exactly the desired bit pattern with only the MSB set. 由于负整数的2的补码表示,最负的整数正是所需的位模式,只有MSB集。 So x |= (unsigned long long )LONG_LONG_MIN; 所以x |= (unsigned long long )LONG_LONG_MIN; should work too. 也应该工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM