ID Number: Q80122
6.00 6.00a 6.00ax
MS-DOS
buglist6.00 buglist6.00a buglist6.00ax fixlist7.00
Summary:
PROBLEM ID: C9201006
SYMPTOMS
When using Microsoft C version 6.0, 6.0a, or 6.0ax, incorrect code
may be generated when using the /Oc, /Oe, /Og, /Ol, /Ox or the
default optimization switch when accessing bit fields within
structures.
If a variable defined to be a pointer to a structure is used and
the structure has elements as the sample code below shows, a field
in the target structure will not be assigned the correct value.
Note: This code fails only if compiling under MS-DOS. Correct Code
is generated if compiling under OS/2.
RESOLUTION
There are several workarounds to this problem:
- Compile using any optimization except those listed above.
- Perform a quick compile using the /qc switch.
- If using pointers, use a temporary variable to assign fields from
the target structure to the source structure. For example:
unsigned temp;
temp=src->f;
tgt->x=temp;
STATUS
Microsoft has confirmed this to be a problem in C versions 6.0,
6.0a, and 6.0ax. This problem was corrected in C/C++ version 7.0.
More Information:
Using the sample code below, assigning a field with bit width 1 in
SOURCE to a field in TARGET using pointers to the corresponding
structures generates incorrect code causing an incorrect value to be
assigned to the target element.
The code generated contains a statement that depends upon the AH
register having been set to the value of the source element previous
to this code. However, the assumption is incorrect because the last
statement to set the AH register is in the call to malloc(). This
assumption can be seen as follows:
;|*** tgt->z=src->f;
; Line 29
*** 000027 8b 1e 00 00 mov bx,WORD PTR _tgt
; The following statement makes the incorrect assumption.
*** 00002b 8a c4 mov al,ah
*** 00002d 32 07 xor al,BYTE PTR [bx]
*** 00002f 25 04 00 and ax,4
*** 000032 31 07 xor WORD PTR [bx],ax
Sample Code
-----------
/* Compile options needed: -Zi to view in CodeView */
#include <malloc.h>
typedef struct
{
unsigned a:1;
unsigned b:1;
unsigned c:6;
unsigned d:1;
unsigned e:1;
unsigned f:1;
}SOURCE;
typedef struct
{
unsigned x:1;
unsigned y:1;
unsigned z:1;
}TARGET;
SOURCE *src;
TARGET *tgt;
void main(void)
{
src=malloc(sizeof(SOURCE));
tgt=malloc(sizeof(TARGET));
src->f=1;
tgt->z=src->f;
}
Additional reference words: 6.00ax 6.00a 6.00