PRB: C 6.0 May Generate Bad Code for Struct Passed by Value

ID Number: Q71284

6.00 6.00a 6.00ax | 6.00 6.00a

MS-DOS | OS/2

buglist6.00 buglist6.00a buglist6.00ax fixlist7.00

Summary:

SYMPTOMS

The Microsoft C Compiler versions 6.0, 6.0a, and 6.0ax will

incorrectly compile the sample program below under large (/AL) or

compact (/AC) memory model when using any optimization other than

/Od. The code generated by the compiler incorrectly sets the DI

register after pushing table[1] and local_var. The attempt to then

access parameter_value is incorrect, as shown by program output

below.

Correct output with /Od:

X: 11.1000 Y: 12.2000

X: 11.1000 Y: 12.2000

Incorrect output without /Od under versions 6.0a and 6.0ax:

X: 0.0000 Y: 190359856625233700000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000000

00000000000000000000000000000000000000000000000000000000000000.0000

X: 0.0000 Y: 190359856625233700000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000000

00000000000000000000000000000000000000000000000000000000000000.0000

Incorrect output without /Od under version 6.0:

X: 0.0000 Y: 190359856625233700000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000000

00000000000000000000000000000000000000000000000000000000000000.0000

X: 11.1000 Y: 12.2000

RESOLUTION

There are several workarounds to this problem:

- Use the /Od option or the /qc (quick compile) option.

-or-

- Pass the structure by reference instead of by value.

-or-

- Use a memory model besides large (/AL) or compact (/AC).

STATUS

Microsoft has confirmed this to be a problem in C versions 6.0,

6.0a, and 6.0ax. This problem has been corrected in Microsoft

C/C++ version 7.0.

More Information:

Sample Code

-----------

/* Compile options needed: /AL

*/

#include <stdio.h>

typedef struct dpoint_str

{

double x, y;

} Dpoint;

Dpoint table[3];

void pointy(Dpoint);

void main(void)

{

Dpoint local_var;

table[0].x = 1.1;

table[0].y = 2.2;

table[1].x = 11.1;

table[1].y = 12.2;

local_var = table[1];

pointy(local_var);

pointy(table[1]);

}

void pointy(Dpoint parameter_value)

{

double local_x;

double local_y;

local_x = parameter_value.x;

local_y = parameter_value.y;

printf("\n X: %7.4lf Y: %7.4lf\n", local_x, local_y);

}

Additional reference words: 6.00 6.00a 6.00ax