[comp.lang.c] shift left arithmetic

aeb@cwi.nl (Andries Brouwer) (09/10/90)

While debugging an Australian computer algebra package
I stumbled over the following: 1<<32 produced 0, but
int a; a=1; a<<32 produced 1. (Of course the word length
of my machine is 32 bits.)
Now I can understand how these values come about, and
each is perfectly acceptable, but shouldnt static evaluation
of expressions produce the same answers as dynamic evaluation?
Is my compiler broken?

[In the application the programmer wrote code depending on
#if 1<<BITS_PER_WORD
; this adds the question whether also the preprocessor should
be consistent in these matters.]

---
main(){
	int a = 1;
	unsigned int b = 1;

	printf("According to the preprocessor, 1<<32 is %s\n",
#if 1<<32
		"nonzero"
#else
		"zero"
#endif
	);

	printf("at compile time it is %d; at run time we get %d %d\n",
		1<<32, a<<32, b<<32);
}
---
According to the preprocessor, 1<<32 is zero
at compile time it is 0; at run time we get 1 1

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/10/90)

In article <2098@charon.cwi.nl> aeb@cwi.nl (Andries Brouwer) writes:
>I stumbled over the following: 1<<32 produced 0, but
>int a; a=1; a<<32 produced 1. (Of course the word length
>of my machine is 32 bits.)
>Now I can understand how these values come about, and
>each is perfectly acceptable, but shouldnt static evaluation
>of expressions produce the same answers as dynamic evaluation?

NO.  When your exceed the bounds of what is guaranteed for the language,
well, there are simply no guarantees.  This example produces explicitly
undefined behavior, and the implementation is free to take whatever
apparently random actions it pleases.

Implementors note:  y=0;...;x<<y; is required to work by the C standard;
on some systems this will require a special-case test in the generated
code, since the hardware shift operation on those systems is incapable
of correctly shifting by 0 bit positions.  (I have seen such machines.)

aeb@cwi.nl (Andries Brouwer) (09/11/90)

vu0310@bingvaxu.cc.binghamton.edu (R. Kym Horsell) writes:

#>While debugging an Australian computer algebra package
#>I stumbled over the following: 1<<32 produced 0, but
#>int a; a=1; a<<32 produced 1. (Of course the word length

#Compiler (may not be) broken -- try 1L<<32. (You didn't
#say that the size of _int_'s was 32 bits).

True, but in fact it was, and 1<<32 and 1L<<32 produce the same results.

ark@alice.UUCP (Andrew Koenig) (09/11/90)

In article <2098@charon.cwi.nl>, aeb@cwi.nl (Andries Brouwer) writes:

> While debugging an Australian computer algebra package
> I stumbled over the following: 1<<32 produced 0, but
> int a; a=1; a<<32 produced 1. (Of course the word length
> of my machine is 32 bits.)

On a machine with 32-bit words, a program that shifts a
vlaue by 32 bits is illegal and the implementation is allowed
to do whatever it likes.
-- 
				--Andrew Koenig
				  ark@europa.att.com

bomgard@copper.ucs.indiana.edu (Tim Bomgardner) (09/11/90)

In article <2101@charon.cwi.nl> aeb@cwi.nl (Andries Brouwer) writes:
}vu0310@bingvaxu.cc.binghamton.edu (R. Kym Horsell) writes:
}
}#>While debugging an Australian computer algebra package
}#>I stumbled over the following: 1<<32 produced 0, but
}#>int a; a=1; a<<32 produced 1. (Of course the word length
}
}#Compiler (may not be) broken -- try 1L<<32. (You didn't
}#say that the size of _int_'s was 32 bits).
}
}True, but in fact it was, and 1<<32 and 1L<<32 produce the same results.

For those who might be interested:

Microsoft C (5.1) produced different results depending on the use of 16
or 32 bit integers, but at least one case would always produce a
non-zero result.  Turbo C 2.0 always produced 0's in all cases.

hp@vmars.tuwien.ac.at (Peter Holzer) (09/11/90)

bomgard@copper.ucs.indiana.edu (Tim Bomgardner) writes:

>}#>I stumbled over the following: 1<<32 produced 0, but
>}#>int a; a=1; a<<32 produced 1. (Of course the word length

>For those who might be interested:

>Microsoft C (5.1) produced different results depending on the use of 16
>or 32 bit integers, but at least one case would always produce a
>non-zero result.  Turbo C 2.0 always produced 0's in all cases.

On the same computer?

On the 8086, all bits of the bit count are significant, so the result should
be 0. On a 80386, however only the rightmost 5 bits are taken, so the result
should be 1 (Of course the 8086 only has 16 bit words, so 32bit shifts are 
done by a library function, which might mask out all but the lower 5 bits;
and neither TC 2.0 nor MSC 5.1 can produce 80386 code, so a 32bit shift is
never done in one instruction with these compilers).
--
|    _	| Peter J. Holzer			| Think of it	|
| |_|_)	| Technische Universitaet Wien		| as evolution	|
| | |	| hp@vmars.tuwien.ac.at			| in action!	|
| __/  	| ...!uunet!mcsun!tuvie!vmars!hp	|     Tony Rand	|