rvillablanca
rvillablanca

Reputation: 1646

Unsigned values in C

I have the following code:

#include <stdio.h>

int main() {
    unsigned int a = -1;
    int b = -1;
    printf("%x\n", a);
    printf("%x\n", b);

    printf("%d\n", a);
    printf("%d\n", b);

    printf("%u\n", a);
    printf("%u\n", b);
    return 0;
}

The output is:

ffffffff
ffffffff
-1
-1
4294967295
4294967295

I can see that a value is interpreted as signed or unsigned according to the value passed to printf function. In both cases, the bytes are the same (ffffffff). Then, what is the unsigned word for?

Upvotes: 32

Views: 263039

Answers (3)

chux
chux

Reputation: 154312

Assign a int -1 to an unsigned: As -1 does not fit in the range [0...UINT_MAX], multiples of UINT_MAX+1 are added until the answer is in range. Evidently UINT_MAX is pow(2,32)-1 or 429496725 on OP's machine so a has the value of 4294967295.

unsigned int a = -1;

The "%x", "%u" specifier expects a matching unsigned. Since these do not match, "If a conversion specification is invalid, the behavior is undefined. If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined." C11 §7.21.6.1 9. The printf specifier does not change b.

printf("%x\n", b);  // UB
printf("%u\n", b);  // UB

The "%d" specifier expects a matching int. Since these do not match, more UB.

printf("%d\n", a);  // UB

Given undefined behavior, the conclusions are not supported.


both cases, the bytes are the same (ffffffff).

Even with the same bit pattern, different types may have different values. ffffffff as an unsigned has the value of 4294967295. As an int, depending signed integer encoding, it has the value of -1, -2147483647 or TBD. As a float it may be a NAN.

what is unsigned word for?

unsigned stores a whole number in the range [0 ... UINT_MAX]. It never has a negative value. If code needs a non-negative number, use unsigned. If code needs a counting number that may be +, - or 0, use int.


Update: to avoid a compiler warning about assigning a signed int to unsigned, use the below. This is an unsigned 1u being negated - which is well defined as above. The effect is the same as a -1, but conveys to the compiler direct intentions.

unsigned int a = -1u;

Upvotes: 34

Santosh A
Santosh A

Reputation: 5361

When you initialize unsigned int a to -1; it means that you are storing the 2's complement of -1 into the memory of a.
Which is nothing but 0xffffffff or 4294967295.

Hence when you print it using %x or %u format specifier you get that output.

By specifying signedness of a variable to decide on the minimum and maximum limit of value that can be stored.

Like with unsigned int: the range is from 0 to 4,294,967,295 and int: the range is from -2,147,483,648 to 2,147,483,647

For more info on signedness refer this

Upvotes: 0

Donotalo
Donotalo

Reputation: 13035

Having unsigned in variable declaration is more useful for the programmers themselves - don't treat the variables as negative. As you've noticed, both -1 and 4294967295 have exact same bit representation for a 4 byte integer. It's all about how you want to treat or see them.

The statement unsigned int a = -1; is converting -1 in two's complement and assigning the bit representation in a. The printf() specifier x, d and u are showing how the bit representation stored in variable a looks like in different format.

Upvotes: 0

Related Questions