one's complement of unsigned char

S

subramanian

Suppose I have the following statement:

unsigned char x = 0;

If I do,

printf("%u\", ~x);

it prints the value of UINT_MAX. I am using Intel machine. This same
result is printed in both VC++ and gcc.

In the second edition of K&R, section A7.4.6 in page 204 says the
following:
"If the operand is unsigned, the result is computed by subracting the
value from the largest value of the promoted type".

Does it mean that since the operand is unsigned, the promoted type is
also unsigned.
 
Z

Zara

Suppose I have the following statement:

unsigned char x = 0;

If I do,

printf("%u\", ~x);

it prints the value of UINT_MAX. I am using Intel machine. This same
result is printed in both VC++ and gcc.

In the second edition of K&R, section A7.4.6 in page 204 says the
following:
"If the operand is unsigned, the result is computed by subracting the
value from the largest value of the promoted type".

Does it mean that since the operand is unsigned, the promoted type is
also unsigned.


x is promoted to unsigned int before applying operator ~. Thus the
result is the one's complement of 0u.

To print the unsigned char that is the one's complement of x, you
should use:

printf("%u\", (unsigned char)(~x));

That, is you should demote it before printing

Zara
 
G

Guest

Zara said:
x is promoted to unsigned int before applying operator ~.

No, x is promoted to /signed/ int. It is only promoted to unsigned int
if UCHAR_MAX > INT_MAX, which is not the case on any machine capable of
running VC++ I'm aware of.
Thus the
result is the one's complement of 0u.

The ~ operator returns the bitwise complement of its operand. One's
complement refers to a particular representation of integers. (I know
you just copied it from the original message.)
To print the unsigned char that is the one's complement of x, you
should use:

printf("%u\", (unsigned char)(~x));

That, is you should demote it before printing

There is a possibility that ~0 is a trap representation. In this case,
it is better to print (unsigned char) ~(unsigned int) x instead, which
is guaranteed to be safe.
 
Z

Zara

No, x is promoted to /signed/ int. It is only promoted to unsigned int
if UCHAR_MAX > INT_MAX, which is not the case on any machine capable of
running VC++ I'm aware of.

Yes, of course, you are right. (STD C-> 6.3.1.1, 2)
The ~ operator returns the bitwise complement of its operand. One's
complement refers to a particular representation of integers. (I know
you just copied it from the original message.)

You are right again.
There is a possibility that ~0 is a trap representation. In this case,
it is better to print (unsigned char) ~(unsigned int) x instead, which
is guaranteed to be safe.

Right again. Anyway, I would prefer to write

(unsigned char) (~(unsigned int) x)

Best regards,

zara
 
J

Jack Klein

x is promoted to unsigned int before applying operator ~. Thus the
result is the one's complement of 0u.

That is quite incorrect. 'x' is promoted to signed int, since signed
into on this platform can hold all values of unsigned char.
 
S

subramanian

unsigned char x = 0;
What is the behaviour of ~x according to the C standard.

After reading K & R, I thought the variable will be promoted to signed
int. Taking bitwise complement should give INT_MAX. But it does not
happen here. I get UINT_MAX.

Can someone clarify my doubt ?
 
P

Peter Nilsson

subramanian said:
unsigned char x = 0;
What is the behaviour of ~x according to the C standard.

Strictly speaking it is undefined on the virtual C machine.
After reading K & R, I thought the variable will be promoted to signed
int.

An unsigned char will be promoted to int if an int can hold all the
values
of unsigned char, otherwise it will be promoted to unsigned int. On
hosted implementations, it will promote to int.
Taking bitwise complement should give INT_MAX.

No, taking the bitwise complement of all bits zero yields all bits one.
There
are three different possible representations for signed integers,[1]
two's
complement, ones' complement and sign-magnitude. The value yielded is
different for each form of representation. Indeed, the 'value' may be a
trap
representation on a ones' complement machine.

[1] Unlike C99, C90 does not specify those representations explicitly,
though Committee members have commented that documents from the
'Normative References' component of C90 imply that those 3 options
are the only ones available to a C90 implementation.
But it does not happen here. I get UINT_MAX.

You snipped the bit of code you used to get that value. You previously
wrote...

printf("%u\", ~x);

Though what you probably meant to post was...

printf("%u\n", ~x);

That code invokes undefined behaviour because %u expects an unsigned
int and you supply a value of type int that is not representable as an
unsigned int (on a 2c machine.)[2]

Try...

printf("%d\n", ~x);

This will yield -1 on a 2c machine.

All that said, bitwise operations should generally only be performed on
unsigned integer types of rank equal or higher than unsigned int. Why?
To avoid the sorts of issues of undefined behaviour that you've
encountered.

[2] Strictly speaking, passing an int for %u invokes undefined
behaviour
even if int value is non-negative.
Can someone clarify my doubt ?

Read the texts very carefully. When working on character types, and
especially when working on bitwise operators, be very careful about
implicit promotions (e.g. integral promotions, usual arithmetic
promotions,
etc...).
 

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

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top