unsigned char and char print

Q

QQ

Hello,

Here is my simple program
int main()
{
unsigned char a =0x81;
char b = 0x81;
printf("unsigned char = 0x%x(%d), char = 0x%x(%d)\n",a,a,b,b);
printf("cast char to unsigned 0x%x\n",(unsigned char)b);
}
~
And here is the print out:
unsigned char = 0x81(129), char = 0xffffff81(-127)
cast char to unsigned 0x81

The result is what I expected, but I couldn't explain it well.
Could someone give me a help and explain to me what 0xfffff81.
(a char is one byte right?)

And is cast here good? if not, is there any other way I can print out a
char 0x81 as 0x81
printf("cast char to unsigned 0x%x\n",(unsigned char)b);
Thanks a lot!
 
M

Martin Ambuhl

QQ said:
Hello,

Here is my simple program
int main()
{
unsigned char a =0x81;
char b = 0x81;

b could be either unsigned or signed. Which is up to the implemntation.
If you want 'b' to be signed, say so. Since UCHAR_MAX may be as low
as 127, and b is signed, you may be assigning an unsigned value to b out
of range. The result of such an assignment is implementation defined.
printf("unsigned char = 0x%x(%d), char = 0x%x(%d)\n",a,a,b,b);

No matter what type b is (unsigned char oe signed char), the above is wrong.
%x is a specifier for unsigned values, %d is a specifier for signed
values. Since a is unsigned, the first %d is wrong.
If b is unsigned, the second %d is wrong. If b is signed, the second
%x is wrong.
printf("cast char to unsigned 0x%x\n",(unsigned char)b);
}
~
And here is the print out:
unsigned char = 0x81(129), char = 0xffffff81(-127)
cast char to unsigned 0x81

The result is what I expected, but I couldn't explain it well.

You have no reasonable expectation as to the output. Your program is
ill-formed.
Could someone give me a help and explain to me what 0xfffff81.
(a char is one byte right?)

It is the int representation of -127. If you use a signed char as an
argument to printf, the usual integer promotions are applied and the
value is passed as a signed int.
 
M

Michael Mair

QQ said:
Here is my simple program

Unfortunately, it also does not compile.

#include said:
int main()

int main (void)
{
unsigned char a =0x81;
char b = 0x81;

Note: "char" is a special integer type; usually, the integer type
name alone gives you the same type as if preceded by "signed".
For char, this is not true; char is a type of its own and can be
either signed or unsigned. Your compiler may even offer you to
choose what kind of char you want to have.

If you mean "signed char", write "signed char". Otherwise, you may
run into surprises for another platform, operating system, compiler
or even other compiler settings.
printf("unsigned char = 0x%x(%d), char = 0x%x(%d)\n",a,a,b,b);

Notes: Because printf() is a variadic function, both a and b
are promoted to signed int and passed in this form. This means
that "x" is the wrong conversion specifier. Cast a and b to
unsigned int if you want %u, %x, %o. If you do not mind that
0 will be output as "0" instead of "0x0", you also could use the
# flag (i.e. %#x instead of 0x%x).
printf("cast char to unsigned 0x%x\n",(unsigned char)b);
}
~
And here is the print out:
unsigned char = 0x81(129), char = 0xffffff81(-127)
cast char to unsigned 0x81

The result is what I expected, but I couldn't explain it well.
Could someone give me a help and explain to me what 0xfffff81.
(a char is one byte right?)

Yes. And you are outputting an int (as explained above).
If you want to print out the _representation_ (the actual bits)
of b, then pass
(unsigned int)(*((unsigned char *)&b))
instead of (unsigned char)b or (the correct version)
(unsigned int)((unsigned char)b)
What is the difference?
(unsigned char) b
takes the value of b and if it does not fit into unsigned char,
then (UCHAR_MAX + 1) is added or subtracted as often as necessary
to have b + N*(UCHAR_MAX+1) or b-N*(UCHAR_MAX+1) in the range
that can be represented by unsigned char.
The other one looks at the address where b is stored, pretends that
this is the address of an unsigned char variable and then interprets
the bit pattern found there as unsigned char value.
And is cast here good?

Casts are only necessary in very few places in C. The arguments of
functions with variable argument list (such as printf()) are one
of these places. Whether the cast really gives you what you want
is another question.

Cheers
Michael
 
M

Michael Mair

Martin said:
b could be either unsigned or signed. Which is up to the implemntation.
If you want 'b' to be signed, say so. Since UCHAR_MAX may be as low
as 127, and b is signed,

ITYM: CHAR_MAX
you may be assigning an unsigned value to b out
of range. The result of such an assignment is implementation defined.


No matter what type b is (unsigned char oe signed char), the above is
wrong.
%x is a specifier for unsigned values, %d is a specifier for signed
values. Since a is unsigned, the first %d is wrong.
If b is unsigned, the second %d is wrong. If b is signed, the second
%x is wrong.

I am not sure about this.
If INT_MAX >= UCHAR_MAX, then I'd expect that effectively
(signed int)a and (signed int)b, respectively, is passed.
Could you please clarify how the signedness is transported
via variable argument lists?

<snip>

Cheers
Michael
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top