Adi
Adi

Reputation: 5179

unsigned int storing signed value

Coming from a typeless language (PHP) I'm a bit confused about datatypes in C. I'm facing the following strange behavior.

//First case
unsigned int a;
a = -1;
printf("a = %u", a); //Outputs a strange number, no problem here

//Second case
unsigned int a;
a = -1;
printf("a = %d", a); //Outputs -1

What I don't understand is how a "contained" a signed value after we specifically said it's unsigned?

How can only formatting the output in the second case do that?

Upvotes: 1

Views: 4896

Answers (4)

Jack
Jack

Reputation: 1616

As other already said you must always keep in mind the difference between a value and its representation, since in C these two concepts are widely separated.

With assignment you put a value into a specific area of memory; with printf() and similar you try to interpret such value.

For clarification try to understand this:

#include <stdio.h>

int main() {   
    int val = 2181448;;
    printf("%s\n", ((char*)&val));   // * Outputs: "HI!"
    return 0;
}   

This will print "HI!" because with the assignment you put in a contiguous area of memory ('int' is at least 4 bytes wide here) the number "2181448", which in hexadecimal is 0x00214948, that is:

  • a byte with value 0x00, that is zero
  • a byte with value 0x21, that is 33 in decimal, that is '!' in ascii
  • a byte with 0x49, that is 73 in decimal, that is 'I' in ascii
  • and finally a byte with value 0x48 that is 72 in decimal that is 'H' in ascii.

If you make printf interpret it as a string (note that the cast is only to avoid compiler warnings) (*due to reverse endianess) you see outputted such number as a 4-length string zero-terminated 'H' 'I' '!' '\0'

Upvotes: 4

Lundin
Lundin

Reputation: 215235

The compiler will translate -1 to the correct signed number format for your system, in 99.9% of all cases this will be two's complement. On a two's complement system with 32 bit ints, -1 will correspond to 0xFFFFFFFF. But if you store that in an unsigned variable, you will get the value 4.29 billion.

You then attempt to print 4.29 billion using the %d format specifier, which is reserved for negative numbers. The program then interprets 0xFFFFFFFF as -1 again.

To sum it up, there is no such thing as negative numbers on a binary level. Depending on how you chose to display the binary, you can form negative numbers. Still, it is all just ones and zeroes: you cannot save a minus sign in a computer memory cell.

Upvotes: 2

Bart Friederichs
Bart Friederichs

Reputation: 33573

Because that is what printf does. It doesn't know the type of the supplied values. So it will take the data it finds in a and interpret it as a signed integer, because you tell it to do so by giving it %d.

printf can also be quite dangerous if you put in the incorrect values for formatting codes, or completely omit them. Your program will crash without any message.

Upvotes: 3

SingerOfTheFall
SingerOfTheFall

Reputation: 29986

The -1 will be represented as something like 10000000 00000000 00000000 00000001 (if int has 4 bytes as in my case). When you are outputting it with %d, the printf() interprets it as a normal int, thus it interprets the leading 1 as the sign, and prints -1. If you output it as %u, printf() knows it's unsigned, and interprets the leading 1 as 2^32, resulting in 4294967295 as output.

Upvotes: 3

Related Questions