In the following code segment what will be:
{ unsigned int x=-1;
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 ;)).
It's because of twos-complement
The flipping of the bits results in a bit pattern that matches -1
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)
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;
}
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