Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

unsigned char promotion with printf [C]

2 views
Skip to first unread message

uberk...@gmail.com

unread,
Feb 6, 2007, 9:48:27 PM2/6/07
to
Hey folks,

I was fiddling with my overflow / underflow of various types on my
machine this evening (I was wanting to find out the value of time_t -
I suspected it was a typedef for long, but I was going down a very
long rabbit trail trying to find the definition of time_t, so I
figured if I underflowed 0 of type time_t, this would tell me the
maximum value of time_t and then I could compare that to various sizes
on my machine... Anyway, while I was fiddling, I tried this bit of
test code:

#include <stdio.h>

int main(void)
{

unsigned char i = 0;

printf("i - 1 = %u\n", i - 1);

return 0;
}

I expected this:

i - 1 = 255

but instead, I got this:

i - 1 = 4294967295

I was scratching my head for a few minutes. 4294967295 happens to be
the maximum value for an unsigned int on my machine, which is a long
way from a char! When I tried something like the following though, I
got the expected result:

#include <stdio.h>

int main(void)
{

unsigned char i = 0;
unsigned char j = i - 1;

printf("i - 1 = %u\n", j);

return 0;
}

i - 1 = 255

Now I am assuming this has to do with some sort of integer type
promotion, but I don't get why it does it the *way* it does it. For
example, I thought the following should work as I expected:

printf("i - 1 = %u\n", i - (unsigned char)1);

But that still printed out 4294967295

So can anyone give me some understanding about what is going on with
this?

R Somers

Jack Klein

unread,
Feb 7, 2007, 1:14:49 AM2/7/07
to
On 6 Feb 2007 18:48:27 -0800, uberk...@gmail.com wrote in
alt.comp.lang.learn.c-c++:

> Hey folks,
>
> I was fiddling with my overflow / underflow of various types on my
> machine this evening (I was wanting to find out the value of time_t -
> I suspected it was a typedef for long, but I was going down a very
> long rabbit trail trying to find the definition of time_t, so I
> figured if I underflowed 0 of type time_t, this would tell me the
> maximum value of time_t and then I could compare that to various sizes
> on my machine... Anyway, while I was fiddling, I tried this bit of
> test code:
>
> #include <stdio.h>
>
> int main(void)
> {
>
> unsigned char i = 0;
>
> printf("i - 1 = %u\n", i - 1);

In the expression above, you are performing a subtraction between two
different types, namely an unsigned char and an integer literal which
has the type signed int. C never performs arithmetic operations
between different types. Instead the type of lesser rank is promoted
to the type of greater rank. In this case, the value of 'n' is
converted to an int value of 1, and your expression "i - 1" yields
exactly the same result as if you had written it "(int)n - (int)1".

Next you pass a negative int value to printf() with a "%u" conversion
specifier, which causes undefined behavior. It just so happens that
on 2's complement platforms that this value has the same
representation as UINT_MAX.

> return 0;
> }
>
> I expected this:
>
> i - 1 = 255

Can't happen, because of the automatic conversion. And this wouldn't
change it either:

i - (unsigned char)1

...because of the integer promotions. C does not perform arithmetic
operations on types of lesser rank than int or signed int. So i would
still get promoted to int, and the expression "(unsigned char)1" would
also get promoted to int, before the two are added yielding an int
result.



> but instead, I got this:
>
> i - 1 = 4294967295
>
> I was scratching my head for a few minutes. 4294967295 happens to be
> the maximum value for an unsigned int on my machine, which is a long
> way from a char! When I tried something like the following though, I
> got the expected result:
>
> #include <stdio.h>
>
> int main(void)
> {
>
> unsigned char i = 0;
> unsigned char j = i - 1;

Here the expression "i - 1" still promotes 'i' to int and performs an
int subtraction generating an int result, but then you assign the
result (-1) to an unsigned char. Assigning -1 to any unsigned integer
type is well-defined in C, it results in the unsigned type containing
its largest possible value. So 'j' becomes 255, on your
implementation.

> printf("i - 1 = %u\n", j);
>
> return 0;
> }
>
> i - 1 = 255
>
> Now I am assuming this has to do with some sort of integer type
> promotion, but I don't get why it does it the *way* it does it. For
> example, I thought the following should work as I expected:
>
> printf("i - 1 = %u\n", i - (unsigned char)1);

I mentioned this above, subtraction requires types of at least int or
unsigned int rank, to not only is 'i' promoted to int, so is
"(unsigned char)1".

> But that still printed out 4294967295
>
> So can anyone give me some understanding about what is going on with
> this?
>
> R Somers

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

0 new messages