BUG: Using float/double Function as Subscript Causes Bad Code

Last reviewed: July 17, 1997
Article ID: Q68921
6.00 6.00a 6.00ax 7.00 | 6.00 6.00a | 1.00 1.50
MS-DOS                 | OS/2       | WINDOWS
kbtool kbbuglist

The information in this article applies to:

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

        - Microsoft C for MS-DOS, versions 6.0, 6.0a, and 6.0ax
        - Microsoft C for OS/2, versions 6.0 and 6.0a
        - Microsoft C/C++ for MS-DOS, version 7.0
        - Microsoft Visual C++ for Windows, versions 1.0 and 1.5
    

SYMPTOMS

Multiple calls to float functions in the same logical statement may cause the floating-point accumulator to be overwritten if the result of one of the calls is used as a subscript. This problem may occur with the Microsoft C Compiler versions 6.0, 6.0a, and 6.0ax, but does not occur when the /qc (quick compile) option is specified.

RESOLUTION

This problem occurs because of the C convention for returning floating point values. To ensure that this problem never occurs, you need to change the usual order of evaluation rules. One way to resolve this problem is to use the PASCAL calling convention.

NOTE: C/C++ 7.0 works with this particular piece of code, however, it is possible that this problem will occur with other samples.

STATUS

Microsoft has confirmed this to be a problem in the products listed at the beginning of this article.

MORE INFORMATION

The sample code below illustrates this problem. Function f_one() returns 0.0 in the floating-point accumulator (__fac). However, the floating-point accumulator is not saved before f_two() is called. The function f_two() returns 12.0 in __fac, which overwrites the 0.0 returned by f_one(). As a result, array[12] is changed, instead of array[0]. As a workaround, the function's return value may be stored in a temporary variable, or the two functions may be declared as _pascal.

Sample Code

/* Compile options needed: none
*/
#include <stdio.h>

float f_one(void); float f_two(void);

float fval[20];

void main(void)
{
   int   i;

// This doesn't work.
   fval[(int)f_one()] = f_two();
   printf("fval[0] (should equal 12.0) = %f\n", fval[0]);

// This works.
   i = (int)f_one();
   fval[i] = f_two();
   printf("fval[0] (should equal 12.0) = %f\n", fval[0]);
}

float f_one() {

   return((float)0.0);
}

float f_two() {

   return((float)12.0);
}


Additional reference words: 1.00 1.50 6.00 6.00a 6.00ax 7.00 8.00 8.00c
KBCategory: kbtool kbbuglist
KBSubcategory: CLIss
Keywords : kb16bitonly


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: July 17, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.