I want to get the values of INT_MIN
and INT_MAX
. I've tried ~0
and ~0 >> 1
since the leftmost bit is a sign bit but I got -1
for both of them.
It's so confused that why ~0
doesn't turn out to be 0xffffffff
and ~0 >> 1
to be 0x7fffffff
?
Use:
~0U >> 1
Suffix 'U' for unsigned shift behavior.
so, confused that why not
~0
turns out to be0xffffffff
?
See, what is 0
say in four bytes representation:
BIT NUMBER 31 0
▼ ▼
number bits 0000 0000 0000 0000 0000 0000 0000 0000
▲ ▲
MSB LSB
LSB - Least Significant Bit (numbered 0)
MSB - Most Significant Bit (numbered 31)
Now ~
is bitwise not operator then flips all bits in 0
as:
BIT NUMBER 31 0
▼ ▼
number bits 1111 1111 1111 1111 1111 1111 1111 1111
▲ ▲
MSB LSB
Because of MSB = 1
this representation is treated as negative number and its magnitude is find using 2'complement math that is -1
.
What is 1
? it is:
number bits 0000 0000 0000 0000 0000 0000 0000 0001
▲ ▲
MSB LSB
1's complement of 1
number bits 1111 1111 1111 1111 1111 1111 1111 1110
▲ ▲
MSB LSB
2'complement? Add 1
in one's complement, that is:
number bits 1111 1111 1111 1111 1111 1111 1111 1111
▲ ▲
MSB LSB
this same as when you gets ~0
? that is why you are getting -1
output.
In most implementation of C >> operator is defined as an arithmetic right shift, which preserves the sign bit MSB. So ~0 >> 1
is noting but -1
remains same.
6.5.7 [Bitwise shift operators]
5 The result of
E1 >> E2
isE1
right-shiftedE2
bit positions. IfE1
has an unsigned type or ifE1
has a signed type and a nonnegative value, the value of the result is the integral part of the quotient ofE1 / 2E2
. IfE1
has a signed type and a negative value, the resulting value is implementation-defined.
You requirement is what is called unsigned right shift >>
and the behavior you needed can be find using unsigned number that is why I suffixed U
as 0U
.
Because printing INT_MIN and INT_MAX is bit tricky(because of undefined and implementation behavior of setting MSB and bit-overflow) in C so I have written a code as follows:
#include <stdio.h>
#include<limits.h> /* include for CHAR_BIT */
int main(){
int my_int_min = 1U << ((sizeof(int) * CHAR_BIT) - 1);
int my_int_max = ~0U >> 1;
printf("INT_MIN = %d\n", my_int_min);
printf("INT_MAX = %d\n", my_int_max);
return 0;
}
See it executing @codepad, it output is:
INT_MIN = -2147483648
INT_MAX = 2147483647
Note for 32-bit number range is [-2147483648, 2147483647]
that is equals to [-231, 231 -1 ]
.
INT_MIN: -231 == -2147483648 is:
1000 0000 0000 0000 0000 0000 0000 0000
▲ ▲
MSB LSB
In expression 1U << ((sizeof(int) * CHAR_BIT) - 1)
, I shifts first bit the LSB(that is 1) to left most side at MSB, And because in C, setting signed bit is undefined behavior when operand is singed type so I used unsigned one 1U.
6.5.7 [Bitwise shift operators]
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.
Another point to note is I used CHAR_BIT a standard macro defined in limits.h that tells number of bits in one char in a C implementation (remember: A char is always one byte size but number of bits in one bytes can be different on different system not always guaranteed to be 8).
INT_MAX: 231 -1 == 2147483647
0111 1111 1111 1111 1111 1111 1111 1111
▲ ▲
MSB LSB
0 is of type int
. So are ~0
and ~0 >> 1
because of int type promotion
~0 has all 1s in its bit pattern and it's -1 in 2's complement, which is the default representation of most modern implementations.
Right shift in C is implementation defined. But most implementations define >>
as arithmetic shift when the type is signed and logical shift when the type is unsigned
Since ~0
is int
, which is a signed type, ~0 >> 1
will be an arithmetic shift right. Hence the value is sign extended, cause the value to be all 1s
You need to do unsigned(~0) >> 1
or ~0U
There are no ways to get INT_MIN
and INT_MAX
portably because in C there are 3 different signed type implementations beside trap representations and padding bits. That's why standard libraries always define INT_MIN
and INT_MAX
directly with the values
numbers are stored in 2's compliment so ~0
is 0XFFFFFFFF
which is -1 .
so FFFFFFF(1111) >>1
gives (1111)FFFFFFF
= 0XFFFFFFFF
= -1
.
When shifting an unsigned
value, the >>
operator in C is a logical shift
. When shifting a signed
value, the >>
operator is an arithmetic shift
.
So , ~0U >> 1
gives (1111)FFFFFFF
= 0XFFFFFFFF
.
~0
is -1
. Every C implementation that you're likely to run into uses two's complement for signed integers, so 0xffffffff
is -1
(assuming 32-bit integers). ~0 >> 1
is the equivalent of dividing -1
by 2
; since we're doing integer arithmetic, the result is -1
.
The value of an all bit set int
depends on the sign representation that your platform has for int
. This is why the macros INT_MIN
and INT_MAX
were invented, there is no way of computing these values in a portable way.
Based on the wikipedia article, C normally implements an arithmetic shift. That means that when you right-shift the quantity 0xffffffff
, the left-most bit (sign bit) of 1
will be preserved, as you observe.
However, Wikipedia also mentions the following, so you will get a logical shift (result of 0x7fffffff
) if you use the unsigned type.
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.
On a 32bit system, 0
is 0x00000000
. ~
is the bitwise not operator, which turns every 0
bit to 1
and vice versa. Therefore, ~0
(~0x00000000
) gives 0xffffffff
.
This in turn is interpreted as -1
in Two's complement.
User contributions licensed under CC BY-SA 3.0