By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,445 Members | 1,329 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,445 IT Pros & Developers. It's quick & easy.

bitwise complement

P: n/a
Consider the following code:

#include<stdio.h>

int main(void)
{
unsigned char c = 0;

unsigned int i = ~c;

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

return 0;

}

I compiled and ran this with 32-bit VC++ and 32-bit gcc.

In both cases, this code prints 4294967295(which is 2^32 - 1) -
UINT_MAX.

My doubt: since we are taking ~c, should't 255 be assigned to i.

Dec 20 '06 #1
Share this Question
Share on Google+
11 Replies


P: n/a
2006-12-20 <11**********************@79g2000cws.googlegroups. com>,
subramanian wrote:
Consider the following code:

#include<stdio.h>

int main(void)
{
unsigned char c = 0;
unsigned int i = ~c;
printf("i = %u\n", i);
return 0;
}

I compiled and ran this with 32-bit VC++ and 32-bit gcc.

In both cases, this code prints 4294967295(which is 2^32 - 1) -
UINT_MAX.

My doubt: since we are taking ~c, should't 255 be assigned to i.
Whenever a value of char or short type is used in an expression, it
is silently converted to int. This is ridiculous, but required by the
standard.

So, when you use c, it becomes 0 as an int, then ~c is unspecified
(implementation-defined?) but apparently interpreted by your
implementation as -1, then when assigning to an unsigned int, -1 becomes
UINT_MAX.
Dec 20 '06 #2

P: n/a

"subramanian" <su**************@yahoo.comwrote in message
news:11**********************@79g2000cws.googlegro ups.com...
Consider the following code:

#include<stdio.h>

int main(void)
{
unsigned char c = 0;

unsigned int i = ~c;

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

return 0;

}

I compiled and ran this with 32-bit VC++ and 32-bit gcc.

In both cases, this code prints 4294967295(which is 2^32 - 1) -
UINT_MAX.

My doubt: since we are taking ~c, should't 255 be assigned to i.
"The result of the ~ operator is the bitwise complement of its (promoted)
operand (that is,
each bit in the result is set if and only if the corresponding bit in the
converted operand is
not set). The integer promotions are performed on the operand, and the
result has the
promoted type. If the promoted type is an unsigned type, the expression ~E
is equivalent
to the maximum value representable in that type minus E."
Dec 20 '06 #3

P: n/a
Random832 <ra****@random.yi.orgwrites:
Whenever a value of char or short type is used in an expression, it
is silently converted to int. This is ridiculous, but required by the
standard.
The precise rule is:

If an int can represent all values of the original type, the
value is converted to an int; otherwise, it is converted to
an unsigned int.

Because a char might have the same range as unsigned int, this
means that a char could be promoted to unsigned int instead of to
int. (But that's certainly an unusual case.)
--
"I ran it on my DeathStation 9000 and demons flew out of my nose." --Kaz
Dec 20 '06 #4

P: n/a
Random832 wrote:
>
Whenever a value of char or short type is used in an expression, it
is silently converted to int. This is ridiculous, but required by the
standard.
Without invoking "promotion" or anything like it, how would
you propose to evaluate

struct { int a : 7; } x = { 42 };
struct { unsigned int b : 13; } y = { 27 };
struct { int c : 11 } z;
z.c = a.x + b.y;

? Find me a machine whose instruction set includes an operation
for "add signed seven-bit integer to unsigned thirteen-bit integer
producing a signed eleven-bit sum" and I'll concede that you've
justified "ridiculous." Until then, I'll stick with "practical."

(Actually, I once worked on a machine that almost did this,
although it didn't distinguish signed and unsigned arithmetic.
The year was 1969 and the words were 48 bits wide, and there
were two distinct program counter registers, and you could get
the program counters to run backwards, and ... well, they don't
make 'em like that any more.)

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 21 '06 #5

P: n/a
2006-12-21 <e7******************************@comcast.com>,
Eric Sosman wrote:
Random832 wrote:
>>
Whenever a value of char or short type is used in an expression, it
is silently converted to int. This is ridiculous, but required by the
standard.

Without invoking "promotion" or anything like it, how would
you propose to evaluate

struct { int a : 7; } x = { 42 };
struct { unsigned int b : 13; } y = { 27 };
struct { int c : 11 } z;
z.c = a.x + b.y;
Masking. And with the fact that overflows are undefined anyway.

There's no reason, if c is type unsigned char, why ~c should not also be
of type unsigned char.

And there's no reason signedness shouldn't be preserved, though it
didn't matter in the OP's case.
Dec 21 '06 #6

P: n/a
On Wed, 20 Dec 2006 10:01:59 -0800, Ben Pfaff <bl*@cs.stanford.edu>
wrote:
>Random832 <ra****@random.yi.orgwrites:
>Whenever a value of char or short type is used in an expression, it
is silently converted to int. This is ridiculous, but required by the
standard.

The precise rule is:

If an int can represent all values of the original type, the
value is converted to an int; otherwise, it is converted to
an unsigned int.

Because a char might have the same range as unsigned int, this
means that a char could be promoted to unsigned int instead of to
int. (But that's certainly an unusual case.)
I think it's more common than you think.

On the TI DSPs I've worked with:

#define CHAR_BIT 16
sizeof(int) == 1

On this implementation, if a char is unsigned, then it has the same
range as that of an unsigned int.

Regards
--
jay
Dec 21 '06 #7

P: n/a
Random832 wrote:
2006-12-21 <e7******************************@comcast.com>,
Eric Sosman wrote:
>Random832 wrote:
>>Whenever a value of char or short type is used in an expression, it
is silently converted to int. This is ridiculous, but required by the
standard.
Without invoking "promotion" or anything like it, how would
you propose to evaluate

struct { int a : 7; } x = { 42 };
struct { unsigned int b : 13; } y = { 27 };
struct { int c : 11 } z;
z.c = a.x + b.y;

Masking. And with the fact that overflows are undefined anyway.
Well, that's my point: You (probably) cannot work directly
with the operands in their original sizes, but must first convert
them to some other form and work with that other form. That's
exactly C's model: Convert a "small" operand to a "large" equivalent,
perform "large" arithmetic, and convert the result to "small" again.
I really, truly, cannot see why you think it "ridiculous."
There's no reason, if c is type unsigned char, why ~c should not also be
of type unsigned char.
On a machine with a char-sized accumulator you might be right.
But not all machines have such things, and those whose narrowest
arithmetic is wider than char would incur performance penalties
when evaluating expressions with narrow operands. (A naive code
generator might just insert an AND after each operation; a smarter
one might be able to eliminate some of them.)

Even so, you still need promotion rules to handle expressions
with mixed operand widths -- and as long as you've got to have
promotion rules anyhow, why not use them to simplify arithmetic
elsewhere, too?

Remember: The design of C did not drive the design of the
machines it ran on; 'twas the other way about.
And there's no reason signedness shouldn't be preserved, though it
didn't matter in the OP's case.
The ANSI Committee discussed the issue of value-preserving vs.
signedness-preserving promotions at some length, and (one suspects)
with some vigor. There's a fairly extensive summary of the positions
and their consequences in the Rationale.

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 21 '06 #8

P: n/a
2006-12-21 <Q4******************************@comcast.com>,
Eric Sosman wrote:
>
>And there's no reason signedness shouldn't be preserved, though it
didn't matter in the OP's case.

The ANSI Committee discussed the issue of value-preserving vs.
signedness-preserving promotions at some length, and (one suspects)
with some vigor. There's a fairly extensive summary of the positions
and their consequences in the Rationale.
In what way does signedness-preserving conflict with preserving the value?
Dec 21 '06 #9

P: n/a
Eric Sosman <es*****@acm-dot-org.invalidwrites:
Random832 wrote:
>Whenever a value of char or short type is used in an expression, it
is silently converted to int. This is ridiculous, but required by
the standard.

Without invoking "promotion" or anything like it, how would
you propose to evaluate

struct { int a : 7; } x = { 42 };
struct { unsigned int b : 13; } y = { 27 };
struct { int c : 11 } z;
z.c = a.x + b.y;

? Find me a machine whose instruction set includes an operation
for "add signed seven-bit integer to unsigned thirteen-bit integer
producing a signed eleven-bit sum" and I'll concede that you've
justified "ridiculous." Until then, I'll stick with "practical."
[...]

You could require the result to be the same *as if* the machine had
the appropriate operations. (Defining the semantics of seven-bit
signed plus thirteen-bit unsigned is left as an exercise.)

Or you could limit promotion to cases where an operation has two
operands of different types. Currently, everything shorter than int
is promoted regardless of its context. You could say that, for
example, adding a short and a short yields a short result, with no
promotion.

I'm not saying this would be *better*. It might be conceptually
simpler in some cases. On the other hand, many CPUs don't have
sub-word arithmetic operations anyway, so compiler writers would have
to go to some effort to ensure that the generated code acts as if they
did.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 22 '06 #10

P: n/a
Random832 wrote:
2006-12-21 <Q4******************************@comcast.com>,
Eric Sosman wrote:
>>And there's no reason signedness shouldn't be preserved, though it
didn't matter in the OP's case.
The ANSI Committee discussed the issue of value-preserving vs.
signedness-preserving promotions at some length, and (one suspects)
with some vigor. There's a fairly extensive summary of the positions
and their consequences in the Rationale.

In what way does signedness-preserving conflict with preserving the value?
"There's a fairly extensive summary of the positions and
their consequences in the Rationale." Section 6.3.1.1, if you're
a Spock-like stickler for precision.

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 22 '06 #11

P: n/a
Random832 wrote:
Eric Sosman wrote:
.... snip ...
>>
The ANSI Committee discussed the issue of value-preserving vs.
signedness-preserving promotions at some length, and (one
suspects) with some vigor. There's a fairly extensive summary
of the positions and their consequences in the Rationale.

In what way does signedness-preserving conflict with preserving
the value?
Read N897. I disagree with their conclusions. But it's too late.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Dec 22 '06 #12

This discussion thread is closed

Replies have been disabled for this discussion.