can't shift negative numbers to the right in c

不打扰是莪最后的温柔 提交于 2021-02-05 06:25:06

问题


I am going through 'The C language by K&R'. Right now I am doing the bitwise section. I am having a hard time in understanding the following code.

int mask = ~0 >> n;

I was playing on using this to mask n left side of another binary like this. 0000 1111 1010 0101 // random number

My problem is that when I print var mask it still negative -1. Assuming n is 4. I thought shifting ~0 which is -1 will be 15 (0000 1111).

thanks for the answers


回答1:


Performing a right shift on a negative value yields an implementation defined value. Most hosted implementations will shift in 1 bits on the left, as you've seen in your case, however that doesn't necessarily have to be the case.

Unsigned types as well as positive values of signed types always shift in 0 bits on the left when shifting right. So you can get the desired behavior by using unsigned values:

unsigned int mask = ~0u >> n;

This behavior is documented in section 6.5.7 of the C standard:

5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2 .If E1 has a signed type and a negative value, the resulting value is implementation-defined.




回答2:


Right-shifting negative signed integers is an implementation-defined behavior, which is usually (but not always) filling the left with ones instead of zeros. That's why no matter how many bits you've shifted, it's always -1, as the left is always filled by ones.

When you shift unsigned integers, the left will always be filled by zeros. So you can do this:

unsigned int mask = ~0U >> n;
                      ^

You should also note that int is typically 2 or 4 bytes, meaning if you want to get 15, you need to right-shift 12 or 28 bits instead of only 4. You can use a char instead:

unsigned char mask = ~0U;
mask >>= 4;



回答3:


In C, and many other languages, >> is (usually) an arithmetic right shift when performed on signed variables (like int). This means that the new bit shifted in from the left is a copy of the previous most-significant bit (MSB). This has the effect of preserving the sign of a two's compliment negative number (and in this case the value).

This is in contrast to a logical right shift, where the MSB is always replaced with a zero bit. This is applied when your variable is unsigned (e.g. unsigned int).

From Wikipeda:

The >> operator in C and C++ is not necessarily an arithmetic shift. Usually it is only an arithmetic shift if used with a signed integer type on its left-hand side. If it is used on an unsigned integer type instead, it will be a logical shift.

In your case, if you plan to be working at a bit level (i.e. using masks, etc.) I would strongly recommend two things:

  1. Use unsigned values.
  2. Use types with specific sizes from <stdint.h> like uint32_t


来源:https://stackoverflow.com/questions/49396937/cant-shift-negative-numbers-to-the-right-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!