What is the value of ~0 in C?

后端 未结 7 1388
暖寄归人
暖寄归人 2021-01-02 10:22

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 bu

相关标签:
7条回答
  • 2021-01-02 10:40

    ~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.

    0 讨论(0)
  • 2021-01-02 10:43

    Use:

    ~0U >> 1
    

    Suffix 'U' for unsigned shift behavior.

    so, confused that why not ~0 turns out to be 0xffffffff?

    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.

    How?

    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.

    Now >> shift operator?

    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 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.

    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.

    How to print INT_MIN and INT_MAX?

    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 
    

    How does this code work?

    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 讨论(0)
  • 2021-01-02 10:46

    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.

    0 讨论(0)
  • 2021-01-02 10:46

    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.

    0 讨论(0)
  • 2021-01-02 10:52

    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 讨论(0)
  • 2021-01-02 10:56

    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

    0 讨论(0)
提交回复
热议问题