D
Dik T. Winter
>
> No, it needn't. Right shifting a signed, negative integer gives
> implementation-defined results.
In the draft standard it still is undefined behaviour.
>
> No, it needn't. Right shifting a signed, negative integer gives
> implementation-defined results.
>
> In the draft standard it still is undefined behaviour.
CBFalconer said:There is a lot of misinformation in the replies you have received.
Shift operations in C are only portable, and properly defined, on
unsigned objects.
If you want to multiply or divide signed integer quantities by
powers of two, just do so. The operators are '*' and '/'.
Jean-Claude Arbaut said:Le 15/06/2005 16:27, dans [email protected], « Chris
Obviously, I wanted to quote that
"""
The result ofE1 >> E2is E1 right-shifted E2 bit positions. If E1 has an
unsigned type
or if E1 has a signed type and a nonnegative value, the value of the
result is the integral
part of the quotient of E1/ 2E2. If E1 has a signed type and a negative
value, the
resulting value is implementation-defined.
"""
You don't say where your quoting from. In any case, that
text says that right-shifting a negative signed value gets
you an implementation-defined result. Your remark (above)
responds to
However dividing a negative value by a power of 2 will not in general give
the same result as an arithmetic right shift. For example gcc compiled the
code:
int div4(int value)
{
return value/4;
}
into:
_div4:
movl 4(%esp), %eax
testl %eax, %eax
js L4
sarl $2, %eax
ret
.p2align 4,,7
L4:
addl $3, %eax
sarl $2, %eax
ret
I.e. it optimised the division into a shift operation but for negative
values it had to add 3 first to get the rounding right.
Lawrence
This is not true. They are only portable, and properly defined, on
non-negative values. C never shifts objects, it shifts values;
and a
shift of a signed integer which only involves representable non-negative
values is defined.
That is, right-shifting a non-negative signed integer works identically
to right-shifting an unsigned integer, both in C99 and C89. In C99, a
left-shift on a non-negative signed integer is also identical to the
operation done on an unsigned integer, as long as the result is
representable in the signed type; C89 does seem to leave this case
undefined.
This, however, is true. Premature optimisation is the root of all evil.
Lawrence said:That's tricky, a shift works at the representation level,
and in addition
the standard defines the effect on values in some circumstances.
Jean-Claude Arbaut said:Le 16/06/2005 09:55, dans [email protected], « Chris Dollin
Pfff. It was a correction to a previous post where I admit
"it should" was rubbish (yet please admit it's common practice,
since on many processors there is a simple instruction sequence
to do that).
Reference is:
"""
International Standard ISO/IEC 9899, Second edition 1999-12-01,
Programming Languages - C,
Section 6.5.7, p85
"""
Is it sufficiently standard to you ?
Lawrence said:That's tricky, a shift works at the representation level, and in addition
the standard defines the effect on values in some circumstances.
Sosman » said:Disagreeing with L.K. in this forum carries more than a
little chance of making oneself ridiculous, but "fools rush
in" ... Here I go; draw your own conclusions:
Lawrence Kirby said:CBFalconer said:[snip]
There is a lot of misinformation in the replies you have received.
Shift operations in C are only portable, and properly defined, on
unsigned objects.
This is not true. They are only portable, and properly defined, on
non-negative values. C never shifts objects, it shifts values;
That's tricky, a shift works at the representation level, and in addition
the standard defines the effect on values in some circumstances.
and a
shift of a signed integer which only involves representable non-negative
values is defined.
That is, right-shifting a non-negative signed integer works identically
to right-shifting an unsigned integer, both in C99 and C89. In C99, a
left-shift on a non-negative signed integer is also identical to the
operation done on an unsigned integer, as long as the result is
representable in the signed type; C89 does seem to leave this case
undefined.
It doesn't define what happens in terms of value but it stil describes
what happens at the representation level.
On modern x86, gcc can eliminate the jump and use a conditionnal move:
movl 4(%esp), %eax
leal 3(%eax), %edx
cmpl $-1, %eax
cmovle %edx, %eax
sarl $2, %eax
ret
But that has nothing to do with the OP, it's just an optimization trick.
Lawrence Kirby said:On Thu, 16 Jun 2005 10:51:50 -0700, Tim Rentsch wrote:
...
It talks abouyt thinks like "bit positions" which is a description of
representation rather than value.
« Lawrence Kirby » said:On Thu, 16 Jun 2005 12:41:04 +0200, Jean-Claude Arbaut wrote:
...
The point remains the same, the code demonstrates a difference between
division and arithmetic shifting.
Are we reading different documents? The description I read of the
"Bitwise shift operators" (ISO/IEC 9899:1999 (E), section 6.5.7) talks
only about values, not about representations.
The Standard describes the shift operators in terms of
a binary representation, but I think R.B. is right: they
operate on values, not on "the" representations.
Consider
an `int' representation with padding bits: Assuming a shift
whose result is well-defined, the padding bits do not
affect any value bits of that result.
The value/representation question can also be argued
without introducing exotica like padding bits. How are "bit
positions" defined in the first place? Not by reference to a
physical ordering: they could be left-to-right, top-to-bottom,
scattered in some strange pattern that conserves silicon --
they could even have no individual physical existence at all
in a computer built of four-state components each representing
a pair of bits. Nor can they be ordered by their addresses,
since even on a bit-addressable machine C has no way to talk
about the address of anything smaller than a complete `char'.
No, "bit positions" (and the "left" and "right" directions)
can only be described in terms of the powers of two in the
value.
I think the Standard's use of "representation" in describing
the shift operators is just for convenience of exposition, and
does not refer to the "representation" as described in 6.2.6.
Note that in addition to describing the shift result in terms
of bit positions, the Standard also describes it in purely
arithmetic form, as multiplication or division by an integer
power of two -- this latter part only makes sense when applied
to the value, not the representation, of the shifted quantity.
Eric Sosman said:The Standard describes the shift operators in terms of
a binary representation, but I think R.B. is right: they
operate on values, not on "the" representations.
That's a non-issue, really, and not what I wrote. Since the
representation of non-negative integers is pretty well fixed, at least
in the way that the definition of the << and >> operators do, you could
say that they work on representations as much as on values.
However, what Mr. Kirby wrote, and what I objected to, is that shifts
operate on _objects_. They don't do that; which can be proved quite
simply by noting that you can shift constants.
Lawrence Kirby said:I'm not saying shifts work on objects (I don't think I did but if so that
was a mistake), I'm saying that they work at a representation level.
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.