[comp.lang.c] MSC 5.1 bug ??

linden@fwi.uva.nl (Onno van der Linden) (02/21/90)

Was my brain working OK when I saw the program below,after compiling
with Microsoft C 5.1,produce "Yes" as its output??

main()
{
	int	i = 0;
	long	l = -1;

	if (l >= (i&1)) puts("Yes");
	else puts("No");
}

Onno van der Linden
linden@fwi.uva.nl

gary@hpavla.AVO.HP.COM (Gary Jackoway) (02/21/90)

> / hpavla:comp.lang.c / linden@fwi.uva.nl (Onno van der Linden) / 12:27 pm  Feb 20, 1990 /
> Was my brain working OK when I saw the program below,after compiling
> with Microsoft C 5.1,produce "Yes" as its output??
> 
> main()
> {
> 	int	i = 0;
> 	long	l = -1;
> 
> 	if (l >= (i&1)) puts("Yes");
> 	else puts("No");
> }

> Onno van der Linden
> linden@fwi.uva.nl
----------
I verified your result.  Further, if you change the int to a short the
same thing happens.  And the result on UN*X is "No" (at least on HP-UX 7.0).
I played around some more and replaced the "l" with "-1".  Same thing.
The problem seems to be that the binary & operator is returning an
unsigned result, even though the manual says "the type of the result
is the type of the operators after [the usual arithmetic] conversion".
I also put a (short) in front of the "1" and again got "Yes".

This appears to me to be a real bug.

You can work around the problem by saying "(int)(i&1)" or "(long)(i&1)".
Anything to re-sign the result after the "&".  You need to do this, of
course, only when you are mixing bit-wise operators with signed comparisons.

Gary Jackoway

kdq@demott.COM (Kevin D. Quitt) (02/22/90)

    Your head was on right; I couldn't believe it either.  I suspected
then disproved: 1) -1 generated 0x0000FFFF instead of 0xFFFFFFFF, 2) an
unsigned comparison.

    The generated test code is completely bogus.  In fact, it is such a lose
that the optimiser COMPLETELY ELIMINATES THE TEST!



              Code generated with optimization disabled:


$SG106  DB      'yes',  00H
$SG108  DB      'no',  00H

;|***   int             i = 0;
        mov     WORD PTR [bp-2],0       ;i

;|***   long    l = -1;
        mov     WORD PTR [bp-6],-1      ;l
        mov     WORD PTR [bp-4],-1

;|***   if ( l  >=  (i & 1 ) )
        mov     al,BYTE PTR [bp-2]      ;i
        and     ax,1
        sub     dx,dx
        cmp     dx,WORD PTR [bp-4]
        jbe     $JCC37
        jmp     $I104
$JCC37:
        jae     $JCC42
        jmp     $L20001
$JCC42:
        cmp     ax,WORD PTR [bp-6]      ;l
        jbe     $JCC50
        jmp     $I104
$JCC50:
$L20001:
;|***           puts( "yes" );
        mov     ax,OFFSET DGROUP:$SG106
        push    ax
        call    _puts
        add     sp,2

;|***   else
        jmp     $I107
                                $I104:
;|***           puts( "no" );
        mov     ax,OFFSET DGROUP:$SG108
        push    ax
        call    _puts
        add     sp,2
$I107:
;|***    }
$EX101:



              Code generated from optimised compilation:


$SG143  DB      'yes',  00H
$SG145  DB      'no',  00H

;|***   int             i = 0;
        mov     WORD PTR [bp-2],0       ;i

;|***   long    l = -1;
        mov     WORD PTR [bp-6],-1      ;l
        mov     WORD PTR [bp-4],-1
 
;|***   if ( l  >=  (i & 1 ) )
;|***           puts( "yes" );
        mov     ax,OFFSET DGROUP:$SG143
        push    ax
        call    _puts
;|***   else
;|***           puts( "no" );
;|***    }


    Amazing (shake of the head).

kdq
-- 



Kevin D. Quitt                          Manager, Software Development
DeMott Electronics Co.                  VOICE (818) 988-4975
14707 Keswick St.                       FAX   (818) 997-1190
Van Nuys, CA  91405-1266                MODEM (818) 997-4496 Telebit PEP last
34 12 N  118 27 W                       srhqla!demott!kdq   kdq@demott.com

david@csource.oz.au (david nugent) (02/25/90)

In a message dated 22-Feb-90, Kevin D. Quitt writes:

 >Your head was on right; I couldn't believe it either.  I suspected
 >then disproved: 1) -1 generated 0x0000FFFF instead of 0xFFFFFFFF, 2) an
 >unsigned comparison.
 >
 >
 >;|***   if ( l  >=  (i & 1 ) )



This is fairly typical behaviour.  I've seen similar things on a number of compilers, though I can't find any reason why automatic type conversions should do this.

'l' is being resolved as an int prior the comparison.

  Try: 

          if ( l >= (long) (i & 1) )

and you'll get something quite different.


david

--  
     UUCP: ...!munnari!csource!david  <Fido/ACSNET Gate>
 Internet: david@csource.oz.au
  FidoNet: 3:632/348