bitwise operator !!

K

Keith Thompson

Jujitsu Lizard said:
The other posters in this newsgroup are knuckleheads who don't
understand C, computing in general, or digital logic design. Let me
help you out here.
[...]

Perhaps that was meant to be a joke, but considering the later posts
in this thread, perhaps you should reconsider making statements like
that.
 
J

jameskuyper

Jujitsu Lizard wrote:
....
I did not realize that sign-magnitude representation was legal on a machine
with a C compiler (why would any sane person represent integers that way?).

I can't vouch for this from my own personal knowledge, but on
2007-11-28, Doug Gwyn asserted on comp.std.c that

| There are some sign-magnitude DSPs, for example, and at least one
mainframe family (Unisys A) is still in
| production and worthy of being able to support a standard-conformant
C compiler.

I similarly can't vouch for the sanity of the people who designed such
systems, nor do I have any idea what reasons they might give to
justify that choice. However, I'd recommend not suggesting that
they're insane until after you've discovered what those reasons might
be.

As a practical matter, the question is not whether those machine
designers were sane, nor whether their choice was a good one. What
matters was such machines have existed in the past, still do exist,
and are still in use by a fair number of people (which implies that
the choice was probably NOT completely insane). It is inconsistent
with the goals of the C standard to arbitrarily prevent the creation
of conforming implementations of C on such machines.
 
B

Ben Bacarisse

pete said:
Jujitsu said:
blargg said:
:
[...]
As far as the right-shift operator applied to negative numbers,
you'll find
that every compiler known to man either propagates the sign bit into the
leftmost position or else uses 0's (depending on the machine
instructions
chosen). Usually the only unknown is the "fill".

You can get around this if you really need to.

Need to shift a signed number right 5 bits?

if (x<0)
{
result = (x >> 5) | (-1 << (sizeof(int) * 8 - 5);
}
else
{
result = ((unsigned)(x)) >> 5;
}

The above code seems questionable (assumes char is 8 bits, two's
complement where it ORs -1 shifted?, and the unsigned cast at the end is
unnecessary). How about this? (the conversion to unsigned before negation
is to properly handle the most negative value of a signed int on a two's
complement machine)

(x < 0) ? -(int) (-(unsigned) x >> 5) : (x >> 5)

My intent was to bypass the ambiguous handling of the sign
propagation on right shift by masking in bits as if the sign bit had
propagated. In other words, the code I posted was designed to
generate code that would effectively always propagate the sign bit
on right shift.

if (0 > x) {
x = -x;

This can overflow. I would avoid all bit operations on signed types.
 
J

jameskuyper

Jujitsu Lizard wrote:
....
I did not realize that sign-magnitude representation was legal on a machine
with a C compiler (why would any sane person represent integers that way?).

The most recent message from Ben Bacarisse reminds me of one advantage
of the typical sign-magnitude representation: INT_MIN is the same as
the mathematical value of -INT_MAX, which means that the unary '-'
operator always has standard-defined behavior on such implementations.
 
P

Phil Carmody

I thought that shifting a signed integer to the left was perfectly
defined but shifting a signed integer to the right had the bothersome
complexity.

Am I wrong?

At least as wrong as any other knucklehead on the group.

However, the majority of the poeple you're disparaging with
your earlier comment appear to understand C vastly better
than you do.

At least you had the humility to ask if you were wrong when
you displayed your utter, almost painful, ignorance of the
language. Maybe there's hope for you.

But I won't hold my breath.

Phil
 
C

CBFalconer

blargg said:
.... snip ...

BTW, in another message in this thread someone said that shifting
a signed value right is undefined. My copy of the C99 standard
says otherwise:

Your quote (repeated above) specifies implementation-defined. This
also means that you don't know what your code will do on another
compiler or system.
 
C

CBFalconer

blargg said:
Sorry if I'm repeating myself from another message (or forgot the
reason given), but couldn't a compiler on a two's complement
platform do the same thing, define INT_MIN to be -INT_MAX? For
example, if int is 16 bits on such a machine, then INT_MAX would
be 32767 and INT_MIN would be -32767. Then you're guaranteed that
every valid value of an int can be negated properly.

And then, on such a machine, you have an illegal bit pattern for an
integer left over. No other languages or programs on that machine
understand this. What are you going to do with it?
 
C

CBFalconer

pete said:
Jujitsu Lizard wrote:
.... snip ...


if (0 > x) {
x = -x;
x >>= 5;
x = -x;
}

Fatal. If x == INT_MIN on entry to that, you can have undefined
behavior in the x = -x statement. However the simple, and
understandable, x = x / 32 will work.
 
L

lawrence.jones

Jujitsu Lizard said:
I did not realize that sign-magnitude representation was legal on a machine
with a C compiler (why would any sane person represent integers that way?).

Why are floating-point numbers usually represented that way? There are
machines that use the same format for both.
 
J

jameskuyper

blargg said:
jameskuyper wrote: ....

Sorry if I'm repeating myself from another message (or forgot the reason
given), but couldn't a compiler on a two's complement platform do the same
thing, define INT_MIN to be -INT_MAX? For example, if int is 16 bits on
such a machine, then INT_MAX would be 32767 and INT_MIN would be -32767.
Then you're guaranteed that every valid value of an int can be negated
properly.

For sign-and-magnitude or 1's complement representations, that feature
comes at the price of having either two different representations of
0, or a trap representation. For 2's complement representations, it
could also be perfectly legal, but the price is different, and there's
only one possibility: the implementation would have to designate the
bit pattern which would otherwise represent -32768 as a trap
representation.
 
J

jameskuyper

CBFalconer said:
Your quote (repeated above) specifies implementation-defined. This
also means that you don't know what your code will do on another
compiler or system.

You're confusing "implementation-defined value" with "undefined
behavior", which is precisely the distinction he's making. If the
behavior were undefined, as was incorrectly claimed, it would indeed
be the case that "you don't know what your code will do on another
machine", and the implemenation for that other machine has no
obligation to document what that behavior will be.

Since the behavior is in fact implementation-defined, you know that
such code will produce a valid value of the specified type, no matter
which conforming implementation you use. If your code makes no
assumptions about which valid value that is, it will still work (for
instance, it could print out what that value is). You also know that
you can find out what the value will be by reading the
implementation's documentation.
 
N

Nate Eldredge

jameskuyper said:
You're confusing "implementation-defined value" with "undefined
behavior", which is precisely the distinction he's making. If the
behavior were undefined, as was incorrectly claimed, it would indeed
be the case that "you don't know what your code will do on another
machine", and the implemenation for that other machine has no
obligation to document what that behavior will be.

Since the behavior is in fact implementation-defined, you know that
such code will produce a valid value of the specified type, no matter
which conforming implementation you use. If your code makes no
assumptions about which valid value that is, it will still work (for
instance, it could print out what that value is). You also know that
you can find out what the value will be by reading the
implementation's documentation.

Interestingly, if E1 has a signed type and a negative value, then
E1 >> E2 yields an implementation-defined value, but E1 << E2 yields
undefined behavior. (Provided E2 is of an appropriate nonnegative value.)
 
F

Flash Gordon

CBFalconer wrote, On 08/12/08 22:56:
And then, on such a machine, you have an illegal bit pattern for an
integer left over. No other languages or programs on that machine
understand this. What are you going to do with it?

I think the standards committee disagreed with you since they explicitly
allow what you are denigrating. In any case, how do you know the no
other languages would understand it? The most likely time it would occur
is on a processor which would/could trap on it (or possibly do a hard
limit on arithmetic at +/-32767. There are even good reasons for this
behaviour to be desired in signal processing.
 
C

CBFalconer

jameskuyper said:
CBFalconer wrote:
.... snip ...


You're confusing "implementation-defined value" with "undefined
behavior", which is precisely the distinction he's making. If the
behavior were undefined, as was incorrectly claimed, it would
indeed be the case that "you don't know what your code will do on
another machine", and the implemenation for that other machine
has no obligation to document what that behavior will be.

No, I'm not. You have no a-priori knowledge of what that 'other
system' consists, thus you don't know what your code will do.
Implementation-defined is only better than undefined when you are
writing code for exactly one known system, which is adequately
documented. If so, your queries don't belong on c.l.c.
 
C

CBFalconer

Flash said:
I think the standards committee disagreed with you since they
explicitly allow what you are denigrating. In any case, how do you
know the no other languages would understand it? The most likely
time it would occur is on a processor which would/could trap on it
(or possibly do a hard limit on arithmetic at +/-32767. There are
even good reasons for this behaviour to be desired in signal
processing.

I'm not disagreeing with you. I AM disagreeing with the
advisability of implementing blarggs suggestion.
 
N

Nate Eldredge

CBFalconer said:
No, I'm not. You have no a-priori knowledge of what that 'other
system' consists, thus you don't know what your code will do.
Implementation-defined is only better than undefined when you are
writing code for exactly one known system, which is adequately
documented. If so, your queries don't belong on c.l.c.

Well, there is a difference; the possible behavior is more limited. In
particular, you know that E1 >> E2 has a value.

For example, this program:

#include <stdio.h>
int main(void) {
printf("Your system thinks -10 >> 2 == %d. Isn't that nice?\n",
-10 >> 2);
return 0;
}

may print

Your system thinks -10 >> 2 == -2. Isn't that nice?

or

Your system thinks -10 >> 2 == -3. Isn't that nice?

or even

Your system thinks -10 >> 2 == 196. Isn't that nice?

But it may not print

Your system thinks -10 >> 2 == a fish. Isn't that nice?

nor

Your granny wears combat boots!

nor may it crash, nor fail to compile (unless other compiler limitations
intrude), nor cause demons to fly out of my nose.

By contrast, this program:

#include <stdio.h>
int main(void) {
printf("Your system thinks -10 >> 2 == %d. Isn't that nice?\n",
-10 >> 2);
return 0;
}

may do any of those things.

I was trying to imagine an application whereby you first test that >>
has the behavior you want (perhaps by exhaustively trying all
possibilities), and use it from then on, but I suppose the
"implementation defined" value could change over the course of the
program. For instance, the DS9000 may have a mode bit which determines
whether >> uses sign-extension or not, and the mode bit may be toggled
automatically every 666 clock cycles. That would appear to be legal.
 
K

Keith Thompson

CBFalconer said:
No, I'm not. You have no a-priori knowledge of what that 'other
system' consists, thus you don't know what your code will do.

If you mean that you have no such knowledge until you bother to read
the implementation's documentation, then you're right -- but once you
read that documentation, you know what the other system does.
Implementation-defined is only better than undefined when you are
writing code for exactly one known system, which is adequately
documented.

Why exactly one? Suppose I'm writing code for exactly ten known
systems, and I've carefully read the documentation for each of them?
Of course depending on implementation-defined behavior will make my
code less portable than if I depended only on behavior defined by the
standard, but sometimes that's necessary.
If so, your queries don't belong on c.l.c.

Surely discussion how the standard defines the term
"implementation-defined" is topical here.
 
B

Ben Bacarisse

For example, this program:

#include <stdio.h>
int main(void) {
printf("Your system thinks -10 >> 2 == %d. Isn't that nice?\n",
-10 >> 2);
return 0;
}

may print
By contrast, this program:

#include <stdio.h>
int main(void) {
printf("Your system thinks -10 >> 2 == %d. Isn't that nice?\n",
-10 >> 2);
return 0;
}

There is no contrast! Presumably you meant -10 << 2 in the second case.
 
N

Nate Eldredge

Ben Bacarisse said:
There is no contrast! Presumably you meant -10 << 2 in the second case.

Argh, I could have sworn I changed it. Yes, you're right.
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top