Arithmetic shift operation in C

  • Thread starter Mehta Shailendrakumar
  • Start date
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.
 
D

Dik T. Winter

>
> In the draft standard it still is undefined behaviour.

My reading abilities apparently deteriorate when it is getting late.
Implementation-defined it is indeed.
 
R

Richard Bos

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.

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.
If you want to multiply or divide signed integer quantities by
powers of two, just do so. The operators are '*' and '/'.

This, however, is true. Premature optimisation is the root of all evil.

Richard
 
C

Chris Dollin

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

with

implying that this is the expected - C-defined- result.
Since the result is *implementation*-defined, it's not
required by C.

[The implementation *could* always return 0. Or 17.]
 
J

Jean-Claude Arbaut

Le 16/06/2005 09:55, dans [email protected], « Chris Dollin »
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

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 ?
 
J

Jean-Claude Arbaut

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

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.
 
L

Lawrence Kirby

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.
This, however, is true. Premature optimisation is the root of all evil.

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
 
P

pete

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.

Arithmetic right shifting a -1 may or may not yield a negative zero.
 
C

Chris Dollin

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).

Jolly good.

[It may be common practice; that wasn't the question. In fact,
given that it *is* common practice, it's even more important
to stress that it's *not specified by the language*, since
"common" is not "universal".]
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 ?

Oh, yes. It's just that you didn't say so in the original.
 
E

Eric Sosman

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.

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:

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.

Here's a hypothetical `int' with one sign bit, fifteen
value bits, and two padding bits:

P S V V V V V V V P V V V V V V V V
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0

(I intend this to mean that the value of the `int' is 256,
that the leftmost padding bit is set, and that the padding
bit in the middle is clear.) Right-shifting this by one
position gives

P S V V V V V V V P V V V V V V V V
x 0 0 0 0 0 0 0 0 x 1 0 0 0 0 0 0 0

(Meaning: the value is 128, and the two padding bits have
unknown settings.)

Observe that the leftmost padding bit does not shift
into the sign position, nor does the middle padding bit
shift into the 128's position, nor does the 256's bit shift
into the middle padding position and get "swallowed" there.
The shift has affected the value bits in a way that is not
influenced by either of the padding bits. That is, the shift
has operated on the value, not on the representation.

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.
 
J

Jean-Claude Arbaut

Le 16/06/2005 18:01, dans [email protected], « Eric
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:

I wouldn't agree with somebody just because of its name ;-)
Just as I would not agree with a math proof just because
a great mathematician has written it.

Still, Lawrence Kirby advice are more than interesting...
 
T

Tim Rentsch

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.

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.
 
L

Lawrence Kirby

On Thu, 16 Jun 2005 12:41:04 +0200, Jean-Claude Arbaut wrote:

....
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.

The point remains the same, the code demonstrates a difference between
division and arithmetic shifting.

Lawrence
 
T

Tim Rentsch

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.

It seems clear from context in the rest of the paragraph that these
phrases refer to bit positions of the value, not bit positions of the
representation. Yes? If it isn't clear then perhaps the language
should be changed to reflect that, because it seems obvious that this
interpretation is what was intended.

6.5.7

4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated
bits are filled with zeros. If E1 has an unsigned type, the value of
the result is E1 x 2**E2, reduced modulo one more than the maximum
value representable in the result type. If E1 has a signed type and a
nonnegative value, and E1 x 2**E2 is representable in the result type,
then that is the resulting value; otherwise, the behavior is
undefined.

5 The result of E1 >> E2 is 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 / 2**E2. If E1 has signed type and a negative value, the resulting
value is implementation-defined.
 
J

Jean-Claude Arbaut

Le 16/06/2005 20:11, dans (e-mail address removed),
« 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.


Yes, of course. I would not try to beat you on your territory ;-)
 
L

Lawrence Kirby

On Thu, 16 Jun 2005 10:51:50 -0700, Tim Rentsch wrote:

....
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.

It talks abouyt thinks like "bit positions" which is a description of
representation rather than value.

Lawrence
 
L

Lawrence Kirby

On Thu, 16 Jun 2005 12:01:56 -0400, Eric Sosman wrote:

....
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.

You're making a distinction there but it is one that makes a
difference?
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.

I certainly agree that the standard is talking about non-padding
bits. But given that is this abstract representation you'rer
referring to any different from the underlying object
representation?

....
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.

Agreed. And the representation of an integer type on a particular
platform must attribute binary weightings to the value bits.
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.

I see no inconsistency in assuming that it does.
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.

Absolutely. The standard defines the shift in terms of representation.
Under the conditions this implies a well-defined numerical result it
specifies that as well.

Lawrence
 
R

Richard Bos

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.

Richard
 
L

Lawrence Kirby

On Fri, 17 Jun 2005 09:18:05 +0000, Richard Bos wrote:

....
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.

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.

Lawrence
 
R

Richard Bos

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.

True. It wasn't you who brought up objects, it was Mr. Falconer. My
excuses.

Richard
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,016
Latest member
TatianaCha

Latest Threads

Top