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

x == 0 && (x & -1) != 0 for negative zero?

P: n/a
As far as I can tell, (x & -1) is nonzero if the integer x is
negative zero. So for signed types, x == 0 does not guarantee
(x & foo) == 0. Is that right? (Not that I expect to ever
encounter a non-two's-complement machine. Just wondering.)

--
Hallvard
Sep 11 '07 #1
Share this Question
Share on Google+
23 Replies


P: n/a
I wrote:
As far as I can tell, (x & -1) is nonzero if the integer x is
negative zero.
Er, for one's complement anyway. To get weirdness with
sign/magnitude as well, we'd need x == 0 && (x ^ 1) < 0.
Or (x >1) != 0, but that's implementation-defined.
So for signed types, x == 0 does not guarantee
(x & foo) == 0. Is that right? (Not that I expect to ever
encounter a non-two's-complement machine. Just wondering.)
--
Hallvard
Sep 11 '07 #2

P: n/a
Hallvard B Furuseth wrote:
I wrote:
>As far as I can tell, (x & -1) is nonzero if the integer x is
negative zero.

Er, for one's complement anyway. To get weirdness with
sign/magnitude as well, we'd need x == 0 && (x ^ 1) < 0.
Or (x >1) != 0, but that's implementation-defined.
>So for signed types, x == 0 does not guarantee
(x & foo) == 0. Is that right? (Not that I expect to ever
encounter a non-two's-complement machine. Just wondering.)
Why would you ever use bitwise operations on signed operands? Bitwise
logic implies that you've got some bitmap, the natural (and the C) model
for it is an unsigned type. [And I suppose you meant (unsigned)-1.]
-- Ark

Sep 12 '07 #3

P: n/a
Ark Khasin writes:
>Hallvard B Furuseth wrote:
>>I wrote:
>>As far as I can tell, (x & -1) is nonzero if the integer x is
negative zero.

Er, for one's complement anyway. To get weirdness with
sign/magnitude as well, we'd need x == 0 && (x ^ 1) < 0.
Or (x >1) != 0, but that's implementation-defined.
>>So for signed types, x == 0 does not guarantee
(x & foo) == 0. Is that right? (Not that I expect to ever
encounter a non-two's-complement machine. Just wondering.)

Why would you ever use bitwise operations on signed operands? Bitwise
logic implies that you've got some bitmap, the natural (and the C) model
for it is an unsigned type.
Bitwise logic implies that bitwise operations are useful at the moment.
Could be just for e.g. 'a & 15' instead of 'a / 16'.

Bit operations on signed integers are common enough, e.g. if one knows
that only a fwe of the least siginificant bits are used.

Also the choice of type for a variable depends on all the ways it's
used, including things like the API for passing it, how it's
read/written, and what other integer types it will meet.
[And I suppose you meant (unsigned)-1.]
No, (unsigned)-1 is not signed.

--
Hallvard
Sep 13 '07 #4

P: n/a
Hallvard B Furuseth wrote:
Bitwise logic implies that bitwise operations are useful at the moment.
Could be just for e.g. 'a & 15' instead of 'a / 16'.
Those are not the same (think of negative a). `a & 15U` is the same as
`a / 16U` if sizeof(a) <=sizeof(unsigned). But I want to see a compiler
that doesn't optimize the latter.
>
Bit operations on signed integers are common enough,
which doesn't make it a good practice
e.g. if one knows
that only a fwe of the least siginificant bits are used.
>
Also the choice of type for a variable depends on all the ways it's
used, including things like the API for passing it, how it's
read/written, and what other integer types it will meet.
Yes. Designing good API is not for the faint of heart. Which fact
doesn't change the point.

-- Ark
Sep 16 '07 #5

P: n/a
Ark Khasin wrote:
>
Hallvard B Furuseth wrote:
Bitwise logic implies that bitwise operations
are useful at the moment.
Could be just for e.g. 'a & 15' instead of 'a / 16'.
Those are not the same (think of negative a). `a & 15U` is the same as
`a / 16U` if sizeof(a) <=sizeof(unsigned).
But I want to see a compiler
that doesn't optimize the latter.
(a & 15) is closer to (a % 16) than to (a / 16)

--
pete
Sep 16 '07 #6

P: n/a
Ark Khasin writes:
>Hallvard B Furuseth wrote:
>Bitwise logic implies that bitwise operations are useful at the moment.
Could be just for e.g. 'a & 15' instead of 'a / 16'.
Duh, a%16 as pete says.
Those are not the same (think of negative a).
They are the same if you know, which you sometimes do, that
a is nonnegtive. _Unless_ (negative zero) & 15 can be 15.
(...)
>Bit operations on signed integers are common enough,
which doesn't make it a good practice
What is not good practice is to make a strict rule out of a general
guideline like "be careful about signed bit operations". Or "avoid
goto".
>e.g. if one knows
that only a fwe of the least siginificant bits are used.
>Also the choice of type for a variable depends on all the ways it's
used, including things like the API for passing it, how it's
read/written, and what other integer types it will meet.

Yes. Designing good API is not for the faint of heart.
Indeed. And two things to keep in mind is that (a) the API can be more
important than how a function works internally, and (b) the API may
anyway be imposed by something or someone else.
Which fact doesn't change the point.
The point is that I asked a technical question about code which
occurs every now and then, and I wondered if that code is correct.

--
Hallvard
Sep 17 '07 #7

P: n/a
"Hallvard B Furuseth" <h.**********@usit.uio.noa écrit dans le message de
news: hb**************@bombur.uio.no...
Ark Khasin writes:
>>Hallvard B Furuseth wrote:
>>Bitwise logic implies that bitwise operations are useful at the moment.
Could be just for e.g. 'a & 15' instead of 'a / 16'.

Duh, a%16 as pete says.
>Those are not the same (think of negative a).

They are the same if you know, which you sometimes do, that
a is nonnegtive.
You the programmer may know that, but if the compiler cannot determine for
sure that the value is always positive, it has to generate code that can
handle all cases. Since division truncates toward zero, ASR (arithmetic
right shift for division) or bitmask (for modulo) is not a solution, it has
to be corrected for negative values, which can be done through appropriate
bit trickery (on 2s complement architectures ;-).
If you know a can only hold positive values, you can tell the compiler by
casting it as unsigned (how ugly!) or you can use the shift or mask
operations (if the divisor is an explicit power of two).
_Unless_ (negative zero) & 15 can be 15.
I don't think that's possible.
but negative_zero >4 invokes UB anyway.
>>Bit operations on signed integers are common enough,
which doesn't make it a good practice

What is not good practice is to make a strict rule out of a general
guideline like "be careful about signed bit operations". Or "avoid
goto".
There is one good thing about right shifting negative values: the result is
implementation defined, not undefined behaviour. You can rely on this
operation having consistent behaviour for a given implementation.

--
Chqrlie.
Sep 18 '07 #8

P: n/a
Charlie Gordon writes:
>"Hallvard B Furuseth" <h.**********@usit.uio.noa écrit dans le message de
news: hb**************@bombur.uio.no...
>Ark Khasin writes:
>>>Hallvard B Furuseth wrote:
Bitwise logic implies that bitwise operations are useful at the moment.
Could be just for e.g. 'a & 15' instead of 'a / 16'.

Duh, a%16 as pete says.
>>Those are not the same (think of negative a).

They are the same if you know, which you sometimes do, that
a is nonnegtive.

You the programmer may know that, but if the compiler cannot determine
for sure that the value is always positive, it has to generate code
that can handle all cases. (...) If you know a can only hold positive
values, you can tell the compiler by casting it as unsigned (how
ugly!) or you can use the shift or mask operations (if the divisor is
an explicit power of two).
Yes. So despite purist "don't use bit operations on signed values",
doing that does make sense at times and is done at times.

Except, that should be "nonnegative", not "positive" (which means larger
than zero), and of course the compiler sometimes can know if a value is
nonnegative, regardless of its signedness.
>_Unless_ (negative zero) & 15 can be 15.

I don't think that's possible.
Why not? Does the standard say? That's what I'm asking about.
but negative_zero >4 invokes UB anyway.
I suspect so, yes. Which is one reason I asked about the
"gentler" bit operations, & and |. (If even they can
produce nonzero, certainly >can.)

--
Hallvard
Sep 18 '07 #9

P: n/a
Hallvard B Furuseth wrote:
Charlie Gordon writes:
>"Hallvard B Furuseth" <h.**********@usit.uio.noa écrit:
.... snip ...
>
>>_Unless_ (negative zero) & 15 can be 15.

I don't think that's possible.

Why not? Does the standard say? That's what I'm asking about.
>but negative_zero >4 invokes UB anyway.

I suspect so, yes. Which is one reason I asked about the
"gentler" bit operations, & and |. (If even they can produce
nonzero, certainly >can.)
The only form -0 can take, in an int, ignoring padding bits and
expressing the result as a hex 16 bit value (for other lengths
insert more copies of the middle bits) are:

0x0000 2's complement
0xFFFF 1's complement
0x8000 sign/magnitude.

Since these are the only representations allowed in C, it is
obvious that a masking operation can only produce 15 for a 1's
complement machine.

With any luck, this will exterminate this thread.

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

--
Posted via a free Usenet account from http://www.teranews.com

Sep 19 '07 #10

P: n/a
On Tue, 18 Sep 2007 16:57:50 -0400, CBFalconer wrote:
The only form -0 can take, in an int, ignoring padding bits and
expressing the result as a hex 16 bit value (for other lengths insert
more copies of the middle bits) are:

0x0000 2's complement
0xFFFF 1's complement
0x8000 sign/magnitude.
The only forms negative zero can take are:

0xFFFF 1s' complement
0x8000 sign/magnitude.

Negative zero doesn't exist in 2's complement. And the only forms -0 can
take are:

0x0000 2's complement
0x0000 1s' complement
0x0000 sign/magnitude.

since -0 is not negative zero regardless of representation.
Sep 19 '07 #11

P: n/a
Op Wed, 19 Sep 2007 16:49:08 +0000 (UTC) schreef $)CHarald van D)&k:

<snip>
Negative zero doesn't exist in 2's complement. And the only forms -0 can
+0 ;-)
take are:

0x0000 2's complement
0x0000 1s' complement
0x0000 sign/magnitude.

since -0 is not negative zero regardless of representation.
+0
--
Coos
Sep 19 '07 #12

P: n/a
On Wed, 19 Sep 2007 19:03:07 +0200, Coos Haak wrote:
Op Wed, 19 Sep 2007 16:49:08 +0000 (UTC) schreef $)CHarald van D)
&k:
>
<snip>
>Negative zero doesn't exist in 2's complement. And the only forms -0
can
+0
;-)
>take are:

0x0000 2's complement
0x0000 1s' complement
0x0000 sign/magnitude.

since -0 is not negative zero regardless of representation.
+0
My point was that -0 is always the same thing as +0. -0 is not allowed to
give you a negative zero.
Sep 19 '07 #13

P: n/a
$)CHarald van D)&k wrote:
CBFalconer wrote:
>The only form -0 can take, in an int, ignoring padding bits and
expressing the result as a hex 16 bit value (for other lengths
insert more copies of the middle bits) are:

0x0000 2's complement
0xFFFF 1's complement
0x8000 sign/magnitude.

The only forms negative zero can take are:

0xFFFF 1s' complement
0x8000 sign/magnitude.

Negative zero doesn't exist in 2's complement. And the only forms
-0 can take are:
No, in 2's complement (-ve zero == +ve zero). Both are zero.
However, in all systems, ((-0 + +0) == 0) :-)

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

--
Posted via a free Usenet account from http://www.teranews.com

Sep 20 '07 #14

P: n/a
In article <fc**********@news6.zwoll1.ov.home.nl=?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0Fk?= <tr*****@gmail.comwrites:
My point was that -0 is always the same thing as +0. -0 is not allowed to
give you a negative zero.
Where in the standard is that stated? Note that on 1's complement
machines negative and positive zero compare as equal.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Sep 20 '07 #15

P: n/a
Dik T. Winter wrote:
In article <fc**********@news6.zwoll1.ov.home.nl>
=?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0Fk?=
<tr*****@gmail.comwrites:
My point was that -0 is always the same thing as +0. -0 is
not allowed to give you a negative zero.

Where in the standard is that stated? Note that on 1's
complement machines negative and positive zero compare as
equal.
| 6.2.6.2 (Representations of) Integer types, p3.
| If the implementation supports negative zeros, they shall be
| generated only by:
| — the &, |, ^, ~, <<, and >operators with arguments that
| produce such a value;
| — the +, -, *, /, and % operators where one argument is a
| negative zero and the result is zero;
| — compound assignment operators based on the above cases.
| It is unspecified whether these cases actually generate a
| negative zero or a normal zero, and whether a negative zero
| becomes a normal zero when stored in an object.

That forbids -0 to be negative zero.

Ralf
Sep 20 '07 #16

P: n/a
On Wed, 19 Sep 2007 22:09:41 -0400, CBFalconer wrote:
$)CHarald van D)&k wrote:
>CBFalconer wrote:
>>The only form -0 can take, in an int, ignoring padding bits and
expressing the result as a hex 16 bit value (for other lengths insert
more copies of the middle bits) are:

0x0000 2's complement
0xFFFF 1's complement
0x8000 sign/magnitude.

The only forms negative zero can take are:

0xFFFF 1s' complement
0x8000 sign/magnitude.

Negative zero doesn't exist in 2's complement. And the only forms -0
can take are:

No, in 2's complement (-ve zero == +ve zero). Both are zero.
This is the definition of negative zero, from 6.2.6.2p2:
"Which of these applies is implementation-defined, as is whether the
value with sign bit 1 and all value bits zero (for the first two), or
with sign bit and all value bits 1 (for ones' complement), is a trap
representation or a normal value. In the case of sign and magnitude and
ones' complement, if this representation is a normal value it is called a
/negative zero/."

Negative zero doesn't exist in 2's complement. It's not equal to positive
zero. It simply doesn't exist.
However,
in all systems, ((-0 + +0) == 0) :-)
Yes, because -0 is the same thing as +0 and plain 0, and because negative
zero compares equal to normal zero. But negative zero plus normal zero is
allowed to give you a negative zero.
Sep 20 '07 #17

P: n/a
Op Thu, 20 Sep 2007 16:56:14 +0000 (UTC) schreef Ralf Damaschke:
Dik T. Winter wrote:
>In article <fc**********@news6.zwoll1.ov.home.nl>
=?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0Fk?=
<tr*****@gmail.comwrites:
>>My point was that -0 is always the same thing as +0. -0 is
not allowed to give you a negative zero.

Where in the standard is that stated? Note that on 1's
complement machines negative and positive zero compare as
equal.

| 6.2.6.2 (Representations of) Integer types, p3.
| If the implementation supports negative zeros, they shall be
| generated only by:
| ¡X the &, |, ^, ~, <<, and >operators with arguments that
| produce such a value;
| ¡X the +, -, *, /, and % operators where one argument is a
| negative zero and the result is zero;
| ¡X compound assignment operators based on the above cases.
| It is unspecified whether these cases actually generate a
| negative zero or a normal zero, and whether a negative zero
| becomes a normal zero when stored in an object.

That forbids -0 to be negative zero.
In 1-complement, a row of only zero-bits represents zero (+0).
A row of only one-bits represents minus zero (-0).
The last sentence of 6.2.6.2 leaves _unspecified_ whether minus zero
becomes plus zero. It doesn't forbid it either.
--
Coos
Sep 20 '07 #18

P: n/a
On Thu, 20 Sep 2007 19:32:46 +0200, Coos Haak wrote:
Op Thu, 20 Sep 2007 16:56:14 +0000 (UTC) schreef Ralf Damaschke:
>Dik T. Winter wrote:
>>In article <fc**********@news6.zwoll1.ov.home.nl>
=?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0Fk?=
<tr*****@gmail.comwrites:
My point was that -0 is always the same thing as +0. -0 is not
allowed to give you a negative zero.

Where in the standard is that stated? Note that on 1's complement
machines negative and positive zero compare as equal.

| 6.2.6.2 (Representations of) Integer types, p3. | If the
implementation supports negative zeros, they shall be | generated only
by:
| — the &, |, ^, ~, <<, and >operators with arguments that | produce
such a value;
| — the +, -, *, /, and % operators where one argument is a | negative
zero and the result is zero; | — compound assignment operators based on
the above cases. | It is unspecified whether these cases actually
generate a | negative zero or a normal zero, and whether a negative zero
| becomes a normal zero when stored in an object.

That forbids -0 to be negative zero.

In 1-complement, a row of only zero-bits represents zero (+0). A row of
only one-bits represents minus zero (-0). The last sentence of 6.2.6.2
leaves _unspecified_ whether minus zero becomes plus zero. It doesn't
forbid it either.
Correct, but that doesn't matter here. It's the first sentence that
matters: -0 (negated plain zero) has none of the bitwise operators, and
doesn't have a negative zero as an operand to any other operator, so it's
not allowed to be negative zero.
Sep 20 '07 #19

P: n/a
CBFalconer writes:
Since these are the only representations allowed in C, it is
obvious that a masking operation can only produce 15 for a 1's
complement machine.
Well, yes. What I wondered was if it _can_ produce 15, or if
I've missed something and it can produce 0:

In C89, I can't find anything so I guess anything goes.
In C99, 6.2.6.2p3 says what can _generate_ negative zero and
that it's unspecified whether that becomes normal zero when
stored in an object. I find nothing else which says an
existing negative zero can be converted to normal zero.
With any luck, this will exterminate this thread.
Har har.

--
Hallvard
Sep 20 '07 #20

P: n/a
iRo
In data Wed, 19 Sep 2007 16:49:08 +0000 (UTC), $)CHarald van D)&k
<tr*****@gmail.com scrisse:
>On Tue, 18 Sep 2007 16:57:50 -0400, CBFalconer wrote:
>The only form -0 can take, in an int, ignoring padding bits and
expressing the result as a hex 16 bit value (for other lengths insert
more copies of the middle bits) are:

0x0000 2's complement
0xFFFF 1's complement
0x8000 sign/magnitude.

The only forms negative zero can take are:

0xFFFF 1s' complement
0x8000 sign/magnitude.

Negative zero doesn't exist in 2's complement. And the only forms -0 can
take are:

0x0000 2's complement
0x0000 1s' complement
0x0000 sign/magnitude.

since -0 is not negative zero regardless of representation.
pheraps: unsigned i=0; --i;

so it should be "--0" and not "-0"
Sep 21 '07 #21

P: n/a
iRo <xy*@not.inusewrites:
In data Wed, 19 Sep 2007 16:49:08 +0000 (UTC), $)CHarald van D)&k
<tr*****@gmail.com scrisse:
[...]
>>Negative zero doesn't exist in 2's complement. And the only forms -0 can
take are:

0x0000 2's complement
0x0000 1s' complement
0x0000 sign/magnitude.

since -0 is not negative zero regardless of representation.

pheraps: unsigned i=0; --i;
I'm not sure what you're trying to say here. The above decrements i,
setting it to UINT_MAX.
so it should be "--0" and not "-0"
--0 is illegal, since "--" is a single token. Did you mean to apply
unary '-' twice? If so, you can write it as '- -0', or as '-(-0)'
(or, equivalently, just as 0).

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 21 '07 #22

P: n/a
iRo wrote:
>
.... snip ...
>
pheraps: unsigned i=0; --i;

so it should be "--0" and not "-0"
You just generated UINT_MAX.

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

--
Posted via a free Usenet account from http://www.teranews.com

Sep 21 '07 #23

P: n/a
CBFalconer <cb********@yahoo.comwrote:
iRo wrote:
pheraps: unsigned i=0; --i;

so it should be "--0" and not "-0"

You just generated UINT_MAX.
No, he didn't. He generated a constraint violation: the constant 0 is
not a modifiable lvalue.
--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com
Fix your .sig.

Richard
Sep 24 '07 #24

This discussion thread is closed

Replies have been disabled for this discussion.