regarding << and >> operators

O

onkar

#include<stdio.h>
int main(void){
printf("%d %d\n",32<<1,32<<0);
printf("%d %d\n",32<<-1,32<<-0);
<----------------------------------see here
printf("%d %d\n",32>>1,32>>0);
printf("%d %d\n",32>>-1,32>>-0);
<----------------------------------and here

return 0;
}



$ make
gcc -Wall -g -o test test.c
test.c: In function `main':
test.c:4: warning: left shift count is negative
test.c:6: warning: right shift count is negative
$ ./test
64 32
0 32 (1)
16 32
0 32 (2)

Why 0 is printed in (1) and (2) ??
 
W

Walter Roberson

printf("%d %d\n",32<<-1,32<<-0);
printf("%d %d\n",32>>-1,32>>-0);
Why 0 is printed in (1) and (2) ??

You got lucky and it printed out something that you recognize
immediately as being odd. If you had been less lucky, it might have
printed something you were expecting, and you might have then tried
to use the operation in a real program only to discover much too late
that your code was incorrect.

To phrase the above in a blunter form: *any* answer would have been
right, because the result of left or right shifting by a negative
value is undefined in C (as is the result of shifting by more than
the number of bits in the promoted value.)
 
S

santosh

onkar said:
#include<stdio.h>
int main(void){
printf("%d %d\n",32<<1,32<<0);
printf("%d %d\n",32<<-1,32<<-0);
<----------------------------------see here
printf("%d %d\n",32>>1,32>>0);
printf("%d %d\n",32>>-1,32>>-0);
<----------------------------------and here

return 0;
}



$ make
gcc -Wall -g -o test test.c
test.c: In function `main':
test.c:4: warning: left shift count is negative
test.c:6: warning: right shift count is negative
$ ./test
64 32
0 32 (1)
16 32
0 32 (2)

Why 0 is printed in (1) and (2) ??

Shifting by a negative value is undefined in standard C and also
nonsensical.
 
C

Chris Dollin

santosh said:
Shifting by a negative value is undefined in standard C
Yes.

and also nonsensical.

No.

It has an obvious meaning, and one that has been implemented
in at least one machine and at least one programming language.

(So acting on vague memory I googled "vax negative shift" and got
to the interesting http://yarchive.net/comp/shift_instruction.html.
I still haven't managed to recover the langaueg I remember with
neg-shits-t'other-way ...)
 
R

Richard Tobin

Shifting by a negative value is undefined in standard C [...]
and also nonsensical.
No.

It has an obvious meaning, and one that has been implemented
in at least one machine and at least one programming language.

And since the definition of shifting in the standard is in terms of
multiplication or division by 2^N, it would be natural to extend it to
negative shifts.

-- Richard
 
S

santosh

Chris said:
No.

It has an obvious meaning, and one that has been implemented
in at least one machine and at least one programming language.

(So acting on vague memory I googled "vax negative shift" and got
to the interesting http://yarchive.net/comp/shift_instruction.html.
I still haven't managed to recover the langaueg I remember with
neg-shits-t'other-way ...)

Interesting link. Straight from the horse's mouth too. I'll be sure to
read it later. Thanks.
 
C

CBFalconer

Chris said:
No.

It has an obvious meaning, and one that has been implemented
in at least one machine and at least one programming language.

[OT] At the machine level, by giving meaning to negative shift
counts, you can implement a complete set of shifts with only two
instructions: ArithShift and LogicalShift. Two more are needed to
implement rotations. Double the count if you also need to
implement "through carry". One actual shift instruction with a 3
bit detail field will do it all.
[/OT]
 
K

Kenneth Brody

Richard said:
Shifting by a negative value is undefined in standard C [...]
and also nonsensical.
No.

It has an obvious meaning, and one that has been implemented
in at least one machine and at least one programming language.

And since the definition of shifting in the standard is in terms of
multiplication or division by 2^N, it would be natural to extend it to
negative shifts.

But, what happens when the hardware includes bit-shift operators,
and the hardware itself assumes an unsigned shift value? If C were
to say "negative shifts mean shift in the opposite direction", then
every non-constant shift would have to convert:

x << y

to the equivalent of:

( y < 0 ) ? (x >> -y) : (x << y)

(Without the issue of side-effects, of course.)

Hardly an efficient operator, is it?

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
R

Richard Tobin

But, what happens when the hardware includes bit-shift operators,
and the hardware itself assumes an unsigned shift value?

I was giving the matural extensibility of the definition as further
evidence against the nonsensicality of negative shifts, not as an
argument for having them in C. The efficiency argument is,
unfortunately, overwhelming.

-- Richard
 
C

Chris Torek

[OT] At the machine level, by giving meaning to negative shift
counts, you can implement a complete set of shifts with only two
instructions: ArithShift and LogicalShift. Two more are needed to
implement rotations. Double the count if you also need to
implement "through carry". One actual shift instruction with a 3
bit detail field will do it all.
[/OT]

There is a much better way to do the whole thing, using an
extra argument. Consider the following ASCII-art diagram of
an 8-bit "shifter" (larger variants are obvious, but harder to
draw :) ):

val1 val2
ABCDEFGH ijklmnop
\\\ /////
\\\ /////
||||||||
FGHijklm
result

If val1==0, bits A-H are all-zeros, and this computes val2 >> 3,
with val2 unsigned ("logical" shift).

If val1==-1, bits A-H are all-ones, and this computes val2 >> 3,
with val2 signed and its sign bit set ("arithmetic" shift).

If val2==0, bits i-p are all-zeros, and this computes val1 << 5.

If val1==val2, bits F-H are the same as bits n-p, and this computes
(val1 rotateleft 5) or, equivalently, (val2 rotateright 3).

If neither val1 nor val2 is all-zeros or all-ones, and not equal to
each other, this extracts an 8-bit sub-field from two 8-bit values.

The diagram above is of a "funnel shifter", which has three inputs
and one output. The inputs are two values (of some bit-size), and
a bit-index in the range [0..N-1], where N is the number of bits
in the values. (The instruction-set designer must decide whether
the "count" above is 3 or 5; either is OK.)

Note that a single 64-bit funnel shifter can implement 8, 16, or
32-bit shifts and rotates; you just have to arrange for the bits
to be shifted-or-rotated to be in the uppermost and lowermost bits
of the two "value" inputs, then choose the shift count correctly.
 
D

Dik T. Winter

> And since the definition of shifting in the standard is in terms of
> multiplication or division by 2^N, it would be natural to extend it to
> negative shifts.

Perhaps. But what when the shiftcount is a variable that can be
positive or negative? Should there be a run-time check to see
which instruction to use?
 

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,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top