BruceM
BruceM

Reputation: 339

Why is a variable declared as an unsigned int generating a negative value?

I wrote this bit of code to learn about bit shifting. To my surprise, even though I declared x to be an unsigned int, the output includes a negative number, namely when the leftmost bit is set to 1. My question: why? I thought an unsigned int was never negative. Per sizeof(x), x is 4 bytes wide.

Here is the code fragment:

int main(void)
{
    unsigned int x;

    x = 1;

    for (int i = 0; i < 32; i++)
    {
        printf("2^%i = %i\n", i, x);
        x <<= 1;
    }


    return 0;
}

Here is the output:

2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
2^7 = 128
2^8 = 256
2^9 = 512
2^10 = 1024
2^11 = 2048
2^12 = 4096
2^13 = 8192
2^14 = 16384
2^15 = 32768
2^16 = 65536
2^17 = 131072
2^18 = 262144
2^19 = 524288
2^20 = 1048576
2^21 = 2097152
2^22 = 4194304
2^23 = 8388608
2^24 = 16777216
2^25 = 33554432
2^26 = 67108864
2^27 = 134217728
2^28 = 268435456
2^29 = 536870912
2^30 = 1073741824
2^31 = -2147483648

Upvotes: 1

Views: 144

Answers (4)

xXliolauXx
xXliolauXx

Reputation: 1313

According to the C++ reference page on printf, using %i in the string passed to printf means the corresponding argument will be treated as signed decimal integer. This means that your unsigned int will be casted to a signed int. In C++, casting unsigned to signed (and reverse) only changes the interpretation, not the bit values. So setting the leftmost bit to 1 makes the number negative because that is what it corresponds to in signed integer interpretation. To achieve the expected number, use %u instead for unsigned integer interpretation.

Upvotes: 1

Jack
Jack

Reputation: 133619

When you talk about the sign of a integral value in C (C++ and many other programming languages) you are just talking about how you interpret some data.

You must understand that what's stored inside an unsigned int are just bits regardless of the sign, the fact that they behave as "unsigned" when used is a mere interpretation of the value.

So by using %i specifier you are treating it as a signed value, regardless how it is declared. Try with %u which specifies that you want to treat them as unsigned.

Upvotes: 3

dbush
dbush

Reputation: 225197

You're using the %i format specifier, which prints its argument as a signed int.

If you want to print as unsigned, use the %u format specifier.

printf("2^%i = %u\n", i, x);

Upvotes: 3

Vlad from Moscow
Vlad from Moscow

Reputation: 311088

Just use correct conversion symbol

printf("2^%u = %u\n", i, x);

Upvotes: 4

Related Questions