C语言负数右移疑问:~0>>n为何结果仍为-1?
~0 >> n in C: Why You're Getting -1 Instead of the Mask You Expect Hey there! Let's unpack this common bitwise operation gotcha—this trips up a lot of folks learning C, especially when working with signed integers.
First, let's break down what ~0 actually is
In C, int is a signed integer type by default. The expression ~0 flips all bits of 0, which means every bit in the int is set to 1. In two's complement (the standard way signed integers are represented), a bit pattern of all 1s corresponds to -1. That's the starting point here.
Why ~0 >> n gives you -1 instead of your expected mask
The key issue is how C handles right shifts for signed integers:
- For signed integers, the right shift is an arithmetic shift. This means the sign bit (the highest bit) is copied into the empty left positions when shifting.
- Since
~0is -1 (all bits 1), shifting it right any number of times will keep filling the left with 1s. The result is still all bits 1, which is still -1 in two's complement. That's exactly why your print statement shows -1 instead of the 15 (0000 1111) you expected.
How to get the mask you want
If you're trying to create a mask that targets the left n bits of another number (like clearing those bits while keeping the rest), you need to use an unsigned integer for the shift—unsigned integers use logical right shifts, where empty left positions are filled with 0s.
Here's the corrected code:
// Use unsigned literal ~0U to ensure logical right shift unsigned int mask = ~0U >> n;
Or if you specifically need the mask as a signed int (though unsigned is generally better for bitwise operations):
int mask = (unsigned int)~0 >> n;
For your example where n=4:
~0Uis an unsigned integer with all bits set to 1.- Shifting right 4 bits gives you a value where the top 4 bits are 0, and all lower bits are 1. If you're working with 16-bit integers, that's
0xFFF0(binary1111 1111 1111 0000), which will let you clear the left 4 bits of your target number when used with the&operator.
Quick recap
- Signed integer right shifts are arithmetic (preserve the sign bit, fill with 1s for negative numbers)
- Unsigned integer right shifts are logical (fill empty positions with 0s)
- To create the mask you intended, always use unsigned values for this kind of bitwise operation.
内容的提问来源于stack exchange,提问作者TheCaptain

