Why do unsigned int x = -1 and int y = ~0 have the same binary representation?

前端 未结 5 1468
感动是毒
感动是毒 2020-12-15 09:54

In the following code segment what will be:

  • the result of function
  • value of x
  • value of y
    {
         unsigned int x=-1;         


        
相关标签:
5条回答
  • 2020-12-15 10:00

    Its pretty easy. The twos complement representation of -1 is 0xFFFFFFFF. Hence that is what x contains.

    The complement operator (~) flips all the bits. So the complement of 0 is a 32-bit number with all the bits set to 1 or 0xFFFFFFFF.

    Edit: As pointed out int he comments. The answer is not A. If it was then it would be saying 0x7FFFFFFF and 0xFFFFFFFF are the same. They're not. The real answer is C (Assuming MAXUNIT is a typo ;)).

    0 讨论(0)
  • 2020-12-15 10:05

    It's because of twos-complement

    The flipping of the bits results in a bit pattern that matches -1

    0 讨论(0)
  • 2020-12-15 10:08

    Since in the first unsigned int, you put -1, but from the unsigned int point of view it is 0xFFFFFFFF (this is how negative integers are stored into a computer); in the second case the bitwise not does not look at the "kind" at all and "transform" 0 into 1 and viceversa, so all zeros of 0 becomes 1 (looking at bits), so you obtain 0xFFFFFFFF.

    The next question is, why comparing an unsigned integer with a signed integer does not distinguish them? (numerically 4294967295 is not equal to -1 of course, even though their representation in a computer is the same). Indeed it could, but clearly C does not mandate such a distinction, and it is "natural", since processor aren't able to do it of their own (I am not sure about this last sentence being always true, ... but it is for most processor): to take into account this distinction in asm, you have to add extra code.

    From the C point of view, you have to decide if to cast int into unsigned int, or signed int into unsigned int. But a negative number can't be cast into a unsigned one, of course, and on the other hand, an unsigned number could cause overflow (e.g. for 4294967295 you need a 64bit register (or a 33bit regster!) to be able to have it and still be able to calculate its negative value)...

    So likely the most natural thing is to avoid strange casting, and permit a "cpu like" comparison, which in this case lead to 0xFFFFFFFF (-1 on 32 bit) compared to 0xFFFFFFFF (~0 on 32bit), which are the same, and more in genereal one can be considered as MAXUINT (the maximum unsigned integer that can be hold) and the other as -1. (Take a look at your machine limits.h include to check it)

    0 讨论(0)
  • 2020-12-15 10:13

    If you run this program, you will see that the answer a is wrong and c is the correct answer:

    #include <stdio.h>
    #include <limits.h>
    
    int main() {
        unsigned int x=-1;
        int y;
        y = ~0;
        if(x == y)
            printf("same\n");
            if(x==INT_MAX) printf("INT_MAX\n");
            if(x==UINT_MAX) printf("UINT_MAX\n");
        else
            printf("not same");
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-15 10:14

    unsigned int x=-1;

    1 is an integer literal and has type int (because it fits in an int). Unary - applied to an int causes no further promotion so -1 is an int with value -1.

    When converted to an unsigned int modulo 2^N arithmetic is used where N is the number of value bits in an unsigned int. x has the value 2^N - 1 which is UINT_MAX (What's MAX_UNIT?).

    int y;
    y = ~0;
    

    Again 0 is type int, in C all the allowed representations of int must have all the value bits of an int representing 0 as 0. Again no promotion happens for unary ~ so ~0 is an int with all value bits being 1. What it's value is is implementation dependent but it is negative (the sign bit will be set) so definitely neither of UINT_MAX or INT_MAX. This value is stored in y unchanged.

    if(x == y)
        printf("same");
    else
        printf("not same");
    

    In this comparison y will be converted to unsigned int in order to be compared with x which is already an unsigned int. As y has an implementation value, the value after conversion to unsigned int is still implementation defined (although the conversion itself is modulo 2^N and fully specified). The result of the comparison is still implementation defined.

    So in conclusion:

    implementation defined, UINT_MAX, implementation defined

    In practice on ones' complement:

    not same, UINT_MAX, -0 (aka 0)

    sign plus magnitude:

    not same, UINT_MAX, INT_MIN

    two's complement:

    same, UINT_MAX, -1

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