[comp.lang.c] question about shift operator

randy@gtx.com (Randy D. Miller) (11/02/88)

I've seen conflicting information about the shift operator in cases
where operand2 is exactly equal to the number of bits in the object.
E.g., with a 32 bit int, what must the following do?

     int n;
     n <<= 32;

K&R 1st ed. seems to indicate the operation is undefined, but does
the proposed standard change this?  

-- 
Randy D. Miller             (602) 870-1696
GTX Corp., 8836 N. 23rd Ave., Phoenix, AZ 85021
{cbosgd,decvax,hplabs,amdahl,nsc}!sun!sunburn!gtx!randy

guy@auspex.UUCP (Guy Harris) (11/02/88)

>     int n;
>     n <<= 32;
>
>K&R 1st ed. seems to indicate the operation is undefined, but does
>the proposed standard change this?  

No.  If you depend on it doing something in particular, you will lose. 
There exist quite common machines on which shift counts are not taken
modulo the word size (68K) and quite common machines on which it is
(80386), and chances are the compiler will just generate a shift
instruction and not add extra code to check whether the shift count is
larger than the word size.

crossgl@ingr.UUCP (Gordon Cross) (11/02/88)

In article <786@gtx.com>, randy@gtx.com (Randy D. Miller) writes:
> I've seen conflicting information about the shift operator in cases
> where operand2 is exactly equal to the number of bits in the object.
> E.g., with a 32 bit int, what must the following do?
> 
>      int n;
>      n <<= 32;
> 
> K&R 1st ed. seems to indicate the operation is undefined, but does
> the proposed standard change this?  

K&R still applies.  The proposed ANSI standard states:

   "If the right operand is negative or is greater than or equal to the
    width in bits of the promoted left operand, the result is implementation
    defined."

Note the phrase "promoted left operand".  This means that (assuming 16-bit
shorts and 32-bit ints) the value of the expression "shortvar << 16" IS
defined and has the same value as "shortvar * 0x10000"!


Gordon Cross
Intergraph Corp.  Huntsville, AL

gwyn@smoke.BRL.MIL (Doug Gwyn ) (11/03/88)

In article <786@gtx.com> randy@gtx.UUCP (Randy D. Miller) writes:
>     n <<= 32;
>K&R 1st ed. seems to indicate the operation is undefined, but does
>the proposed standard change this?  

It's undefined because the intention is that a raw machine shift
instruction be usable to implement this, and usually such a shift
count cannot be represented in the instruction.  I did see an
architecture once that was unable to represent a 0 shift count,
or rather you could build such an instruction but it didn't work
right!  However, the proposed C standard allows <<0 and >>0.

(By the way, if the count is written as a constant, the compiler
can sometimes use alternate code sequences, e.g.
	n <<= 16
becomes
	SWAP_HALVES
	CLEAR_LOWER
and
	n <<= 100
could become
	CLEAR
It is when a general expression is used for the count that things
get interesting.)

blm@cxsea.UUCP (Brian Matthews) (11/03/88)

Randy D. Miller (randy@gtx.UUCP) writes:
|I've seen conflicting information about the shift operator in cases
|where operand2 is exactly equal to the number of bits in the object.
|E.g., with a 32 bit int, what must the following do?
|     int n;
|     n <<= 32;
|K&R 1st ed. seems to indicate the operation is undefined, but does
|the proposed standard change this?  

From section 3.3.7 "Bitwise shift operators" of the ANSI draft standard,
in the first paragraph under Semantics:

"...If the value of the right operand is negative or greater than or
equal to the width in bits of the promoted left operand, the behavior is
undefined."

-- 
Brian L. Matthews  blm@cxsea.UUCP   ...{mnetor,uw-beaver!ssc-vax}!cxsea!blm
+1 206 251 6811    Computer X Inc. - a division of Motorola New Enterprises

scjones@sdrc.UUCP (Larry Jones) (11/03/88)

In article <786@gtx.com>, randy@gtx.com (Randy D. Miller) writes:
> I've seen conflicting information about the shift operator in cases
> where operand2 is exactly equal to the number of bits in the object.
> K&R 1st ed. seems to indicate the operation is undefined, but does
> the proposed standard change this?  

Nope, the draft says "If the value of the right operand is
negative or is greater than or equal to the width in bits of the
promoted left operand, the behavior is undefined."

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@sdrc.uucp
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150                  AT&T: (513) 576-2070
"Save the Quayles" - Mark Russell

friedl@vsi.COM (Stephen J. Friedl) (11/03/88)

In article <786@gtx.com>, randy@gtx.com (Randy D. Miller) writes:
> I've seen conflicting information about the shift operator in cases
> where operand2 is exactly equal to the number of bits in the object.
> E.g., with a 32 bit int, what must the following do?
> 
>      int n;
>      n <<= 32;
> 
> K&R 1st ed. seems to indicate the operation is undefined, but does
> the proposed standard change this?  

3.3.7  Bitwise shift operators.

Syntax:

	shift_expression:
		additive_expression
		shift_expression << additive_expression
		shift_expression >> additive_expression

Constraints:

	Each of the operands shall have integral type.

Semantics:

	The integral promotions are performed on each operand.
	If the value of the right operand is negative or is
	greater than or equal to the width in bits of the promoted
	left operand, the behavior is undefined.


-- 
Steve Friedl    V-Systems, Inc.  +1 714 545 6442    3B2-kind-of-guy
friedl@vsi.com     {backbones}!vsi.com!friedl    attmail!vsi!friedl
----Nancy Reagan on 120MB SCSI cartridge tape: "Just say *now*"----

root@libove.UUCP (Jay M. Libove) (11/05/88)

From article <786@gtx.com>, by randy@gtx.com (Randy D. Miller):
> I've seen conflicting information about the shift operator in cases
> where operand2 is exactly equal to the number of bits in the object.
> E.g., with a 32 bit int, what must the following do?
> 
>      int n;
>      n <<= 32;

Boy am I confused.

Looking at the above, I read it to be "shift an n-bit integer n bits left"
which would presumably have the following effect:

(let n=8 for simplicity)

i = abcdefgh
shift left one
i = bcdefgh0
shift left one
i = cdefgh00
...
shift left the last time
i = 00000000

Now, why is there any question as to the result?

(One machine test: SCO Xenix 286 v2.2.1 results 0 from

	int x;

	x=0xffff;
	x <<= 16;
	printf("%d\n",x);

)

-- 
Jay Libove		ARPA:	jl42@andrew.cmu.edu or libove@cs.cmu.edu
5731 Centre Ave, Apt 3	BITnet:	jl42@andrew or jl42@drycas
Pittsburgh, PA 15206	UUCP:	uunet!nfsun!libove!libove or
(412) 362-8983		UUCP:	psuvax1!pitt!darth!libove!libove

chris@mimsy.UUCP (Chris Torek) (11/08/88)

In article <192@libove.UUCP> root@libove.UUCP (Jay M. Libove) writes:
>Looking at the above, I read it to be "shift an n-bit integer n bits left"
>... Now, why is there any question as to the result?

Because different machines implement shift-left differently.

>(One machine test ....

Try a better test.

	#define	BITS_PER_CHAR	8	/* needed below */

	int fn();

	main()
	{
		int x = ~0;
		x <<= fn(sizeof(x));
		printf("result of %d << %d is %d\n", ~0, fn(sizeof(x)), x);
		exit(0);
	}

	/*
	 * You may have to put fn() in a separate file if your compiler is
	 * overly clever.
	 */
	int fn(sz) int sz; { return (sz * BITS_PER_CHAR); }

On the VAX, the result of shifting by the (not known to be constant)
value 32 is the same as the result of shifting by zero, because the VAX
looks only at the 5 lowest order bits of the shift count.  It does this
so that right shifts can be done with negative left shifts.  (Note
that, since this is an arithmetic shift and not a rotate, it still
checks the sign bit of the shift count to see whether to propagate the
sign bit of the original value in a rightward shift.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

guy@auspex.UUCP (Guy Harris) (11/09/88)

>Now, why is there any question as to the result?

Because:

	1) the intent was that shifts be implemented using the machine's
	   shift instructions, with as little extra decoration as
	   possible;

and

	2) some machines take the shift count modulo the word size,
	   and others don't, so some machines, when told to shift left
	   (word size) bits, will shift (word size) bits,
	   clearing the word, and others will shift left 0 bits.

The language spec specifically allows for this, by not specifying what
happens if you have a shift count >= (word size).

gwyn@smoke.BRL.MIL (Doug Gwyn ) (11/10/88)

In article <192@libove.UUCP> root@libove.UUCP (Jay M. Libove) writes:
>Now, why is there any question as to the result?

Rewrite the example as
	int n, s;
	s = 32;
	/* ... */
	n << s;
Now tell us what machine instructions will be generated for "n << s".
Then look up the behavior of those instructions when s==32.

mouse@mcgill-vision.UUCP (der Mouse) (11/15/88)

In article <14414@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
> In article <192@libove.UUCP> root@libove.UUCP (Jay M. Libove) writes:
>> Looking at the above, I read it to be "shift an n-bit integer n bits
>> left" ... Now, why is there any question as to the result?
> Because different machines implement shift-left differently.
>> (One machine test ....
> Try a better test.
> [sample program, with shift count not known at compile time]

> On the VAX, the result of shifting by the (not known to be constant)
> value 32 is the same as the result of shifting by zero, because the
> VAX looks only at the 5 lowest order bits of the shift count.

What sort of VAX is this you're talking about, Chris?  The Gray Book,
revision 6.1, dated 20 May 1982, says that the ASHL shift count is a
signed byte.  Then, under "Notes:", it says

    2. If cnt GTR 32 (ASHL) or cnt GTR 64 (ASHQ) the destination
       operand is replaced by 0.

    3. If cnt LEQ -31 (ASHL) or cnt LEQ -63 (ASHQ) all the bits of the
       destintation operand are copies of the sign bit of the source
       operand.

I assume note 2 is supposed to read GEQ instead of GTR, or 31 and 63
instead of 32 and 64.

I tried this and (a) the compiler used an ashl to do the shift and (b)
it worked the way the book says: 1<<32==0.  Machines were a 750 and a
MicroVAX-II.

If a right shift is simply a negative left shift, and it uses only the
low five bits, could you explain the difference between i<<30 and i>>2
to me, please?

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

chris@mimsy.UUCP (Chris Torek) (11/15/88)

In article <1354@mcgill-vision.UUCP> mouse@mcgill-vision.UUCP
(der Mouse) writes:
>What sort of VAX is this you're talking about, Chris?

I must have been thinking about the ROTL instruction...

(Okay, the VAX tries to do << `correctly'.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris