Can you control what a bitwise right shift will fill in C?

匿名 (未验证) 提交于 2019-12-03 01:39:01

问题:

As far as I know when you use a left shift bitwise operator in C it's guaranteed that the vacant bits will be filled with 0s. However, I've read that the right shift is implementation-dependent, meaning in some machines the vacant bits will be filled with 0s, in others they will be filled with 1s.

I am using the right shift in a program, and indeed my machine is filling the vacant bits with 1s. Problem is I would need it to fill with 0s instead.

Is there a way to force 0s to be used on right shifts?

One solution would be, after the right shift is applied, to create a mask like 011111111 and then apply a bitwise AND, which will change the leftmost 1 that was inserted to a 0.

But this is cumbersome and wastes time. If there was a way to tell my machine to fill right shifts with 1s it would be much easier.

Thanks

回答1:

Cast the number to unsigned and then shift. That will force a 0-fill.



回答2:

No, you can't.

Shifts on unsigned types are well defined (as long as the right operand is in non-negative and less than the width of the left operand), and they always zero-fill.

Shifts (or any bitwise operations) on signed types are generally not a good idea. If the left operand is negative then has undefined behavior, and >> yields an implementation-defined result (meaning that the compiler has to document what it does, but there's no way for you to control it). For non-negative values of a signed type, the result is what you'd expect -- as long as it doesn't overflow (if it overflows, the behavior is undefined).

Here's what the C99 standard says (section 6.5.7):

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

The result of E1 E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

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.



回答3:

There are two different right shift operations: arithmetic, and logical.

The logical shift is used with unsigned numbers in C. It always fills in the high bits with zeroes. This is what you need.

The arithmetic shift is used with signed numbers, because it preserves the sign of the number being shifted. If the number is positive, the most significant bit will be 0, and it will fill with 0s. If the number is negative, the most significant bit will be 1, so it will fill with 1s.

Note that in Java, these actually use different operators: >> for arithmetic, >>> for logical. This is needed because Java has no unsigned type.



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