FIX: Use of /Oe with Ternary Operator May Generate Bad Code

Last reviewed: September 18, 1997
Article ID: Q115851
7.00 | 1.00 MS-DOS | WINDOWS kbtool kbfixlist kbbuglist

The information in this article applies to:

  • The Microsoft C/C++ Compiler (CL.EXE), included with:

        - Microsoft C/C++ for MS-DOS, version 7.0
        - Microsoft Visual C++ for Windows, version 1.0
    

SYMPTOMS

The compiler may generate bad code when the /Oe compiler optimization switch is used when compiling code that contains a complex use of the conditional (ternary) operator. The sample code below shows one such case.

CAUSE

This problem is due to an overly aggressive code generation technique which lengthens byte memory references to word memory references in certain cases.

RESOLUTION

You can correct this error by either

  1. removing the /Oe switch

    -or-

  2. disabling the optimization via the #pragma statement

    -or-

  3. simplifying the statement containing the conditional operator

STATUS

Microsoft has confirmed this to be a problem in the C/C++ compiler for MS-DOS, versions 7.0 and 8.0. This problem was corrected in the C/C++ compiler for MS-DOS version 8.0c, which is included in Visual C++ for Windows, version 1.5.

MORE INFORMATION

The following is a fragment of the assembly code generated when compiling the sample code below:

   *** 00001d  26 ff 07          inc   WORD PTR es:[bx]
   *** 000020  26 8e 47 02       mov   es,WORD PTR es:[bx+2]
   *** 000024  26 8b 34          mov   si,WORD PTR es:[si]

The last line of this assembly language fragment is incorrect. The correct assembly language for this would be:

      *** 000021  26 ff 07          inc   WORD PTR es:[bx]
      *** 000024  26 8e 47 02       mov   es,WORD PTR es:[bx+2]
      *** 000028  26 8a 04          mov   al,BYTE PTR es:[si]

Sample Code

/*  compile with these switches: -c -Oe -Fc
*/

struct mystruct {
      unsigned char  _far  *ptr;
      int (*buf)(mystruct _far *);
      short cnt;
};

// #pragma optimize ("e",off)    // Uncomment line to fix problem
void func1(void)
{
      int c;
      mystruct _far *fb = (mystruct far *)0;

      while ((c = (--(fb)->cnt>=0 ?
        ((int)(*((fb)->ptr)++)) : (*(fb)->buf)(fb))) != (-1));
}
// #pragma optimize ("e", on)

void main()
{
  func1();
}


Additional reference words: 1.00 7.00 8.00 register
KBCategory: kbtool kbfixlist kbbuglist
KBSubcategory: CodeGen
Keywords : CodeGen kb16bitonly kbbuglist kbfixlist kbtool
Version : 7.00 | 1.00
Platform : MS-DOS WINDOWS
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: September 18, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.