Mail Archives: djgpp/1998/07/08/19:34:38
On Wed, 08 Jul 1998 22:38:27 +0200, dns AT cyberdude DOT com wrote:
>I use the following code:
>unsigned short s=1;
>unsigned int t=1;
>while ((s<<t)!=0) { // this loop is infinite! but why?
> t++; }
You just discovered a case of undefined behaviour.
When the expression s<<t is evaluated, the left operand s is widened
to int, i.e. (int)s<<t will be executed. You cannot avoid this. That's
how the programming language C is defined. The type of the result will
be int therefore.
According to the C standard, a shift operation is undefined if the
right operand is equal or greater than the bit size of the operand.
The bit size of int is 32 and therefore the expression 1<<32 is
undefined although the "mathematical" result is 0.
The reason why
1 << 32 == 1
in this implementation is the following: The operation is executed as
SHL EAX, CL
with EAX=1 and CL=32
The INTEL specification says that any shift operation will be executed
as
op1 SHIFT (op2 mod 32)
for efficiency reasons. In this case the processor will produce a
SHIFT by 0 and the result is 1.
The operation (unsigned short)(1<<t) will produce 0 whenever t%32 is
in the range 16..31. Therefore (unsigned short)(1<<t) will be 0 if the
increasing t reaches 16 as the cast will cut off bits 16..31 because a
short is 16 bits long.
With BC for DOS you won't have this problem because both short and int
are 16 bit types. In this case 1<<16 is still undefined in theory, but
in this implementation it will work and evaluate to 0, as expected.
Note that
int i=1;
i<<32;
will evaluate to 1 in Borland 16 bit C, too, while the literal
expression 1<<32 will evaluate to 0...
"Undefined" means that a C implemention is not obliged to return a
useful or expected result. But it may return a useful result if it
wishes.
Regards
Horst
- Raw text -