[comp.lang.c] Turbo C bug with unsigned long integer.

demelo@im4u.UUCP (Julio De Melo) (04/21/88)

	I haven't read this news group for a while, and for this reason
I am not sure whether this bug has been reported or not. My apologies if so.

	I wrote a program in Turbo C, which runs on an 8088, that needs an
unsigned long integer (32 bits) that I am using simply as a bit pattern. I
initially load this variable with a single bit one in a specific position
out of the 32 possible. To do this I wrote:

		unsigned long variable;

		...

		variable = 1 << num_shift;

	where :  num_shift < 32;

	The problem is that if num_shift is higher than 14, I get
(I suppose so) unnexpected results. The table below show these
results:

	num_shift	result (variable = ...)

	   14		  16384 (0x4000)	OK!
	   15	       -32768 (0xffff8000)	(???, variable was declared
						 as unsigned)
	   16		    0			(???, variable is long)
	 17-31		    0			(same problem)

	What seems to be happening is that "variable" is treated in memory
as two separate 16-bit words, such that when a shift is performed that
crosses the boundary between them, the one in the MSB of the lower word
is lost.

	To confirm that this is actually happening, I wrote the code below
to test whether "variable" is actually interpreted by the compiler as a
long integer. It works well with the exception of the case for "num_shift"
equal to 31, when the result is  -2^^31, instead of  2^^31 (the hex result
is actually what I intend it to be, 0x80000000, but when printing it I
should get a positive number as output).


      if (num_shift != 15)		/* avoid the -32768 result */
	{
	  variable = 1 << num_shift;	/* shift lower word */
          if (!variable)		/* if zero, shift upper word */
	    variable = 0x10000 << (num_shift - 16);
        }
      else
	variable = 0x8000;


	I have no idea whether this works or not on Quick C.
	Any comments?

		Julio de Melo
		UTexas - Austin
		julio17@emx.utexas.edu

chris@mimsy.UUCP (Chris Torek) (04/21/88)

In article <2658@im4u.UUCP> demelo@im4u.UUCP (Julio De Melo) writes:
>		unsigned long variable;
>		...
>		variable = 1 << num_shift;
>	where :  num_shift < 32;
>	The problem is that if num_shift is higher than 14, I get
>(I suppose so) unnexpected results.

This is not a bug.  To get what you want, you must shift an unsigned
long 1, not an ordinary integer 1.  The result of `1 << num_shift'
is determined by the type of the left-hand operand of `<<', namely
`1'; the shift is thus done in integer precision.  Try

	variable = 1UL << num_shift;

or

	variable = (unsigned long)1 << num_shift;

(the former may not exist in various compilers).
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris