ID Number: Q77822
6.00 6.00a 6.00ax | 6.00 6.00a
MS-DOS | OS/2
buglist6.00 buglist6.00a buglist6.00ax
Summary:
PROBLEM ID: C9110004
SYMPTOMS
In the Microsoft C Compiler versions 6.0, 6.0a, and 6.0ax and in
the Microsoft QuickC Compiler versions 2.5 and 2.51, the addresses
of elements in a union should all be the same; however, in a union
of bit fields, the first bit field has a different address from the
rest of the bit fields. A problem also occurs in the union of a
single bit field with another data type, such as a structure. The
bit field and the structure will not have the same address.
As a result of this incorrect storage, setting the first bit field
of a union of bit fields will not set the other bit fields that
should be in its unit. Similarly, setting any bit field in any unit
but the first will not set the first bit field.
RESOLUTION
To work around this problem, place the bit fields in a structure
instead of a union, or in a structure inside the union. This may be
what was desired in the first place, since multiple bit fields in a
union should all have the same value.
STATUS
Microsoft has confirmed this to be a problem in C versions 6.0,
6.0a, and 6.0ax and in QuickC versions 2.5 and 2.51 (buglist2.50,
buglist2.51). We are researching this problem and will post new
information here as it becomes available.
More Information:
The ANSI standard states:
A member of a structure or union may have any object type. In
addition, a member may be declared to consist of a specified
number of bits.
Therefore, it is legitimate to have one or more bit fields in a union
in C and QuickC. This was not a feature in earlier versions of these
products.
In addition
The size of a union is sufficient to contain the largest of its
members. A pointer to a union object, suitably converted, points
to each of its members (or if a member is a bit field, then to
the unit in which it resides).
Therefore, placing a watch on a bit field in CodeView will give us the
contents of the unit in which the bit field resides and watching the
address of the bit field in CodeView gives us the address of the unit.
Note that this is the only way that we can observe the address of a
bit field, since you cannot use the address-of operator on a bit field
in C.
The following examples illustrate the two situations described in the
SYMPTOMS section of the summary and how to work around them. As
indicated before, CodeView must be used to obtain the address of the
unit that a bit field resides in.
Sample Code 1
-------------
/* Compile options needed: none
*/
/*********************************************************************
To see that the address of the 1st bit field incorrectly differs, watch
&avar.x0 (This one differs)
&avar.x1
&avar.x2
.
.
&avar.x6
&avar.x7
Notice that setting avar.x2 to 1 sets all bit fields but avar.x0 to 1.
They should all be set since they are in a union.
To work around the problem, place the bit fields inside of a structure
inside of the union as y0 - y7 are in sample code 2.
*********************************************************************/
typedef union aa
{
unsigned x0:1;
unsigned x1:1;
unsigned x2:1;
unsigned x3:1;
unsigned x4:1;
unsigned x5:1;
unsigned x6:1;
unsigned x7:1;
}a;
a avar;
void main( )
{
avar.x2 = 1;
}
Sample Code 2
-------------
/* Compile options needed: none
*/
/*********************************************************************
To see that the address of the bit field incorrectly differs, watch
&bvar.one.y0
&bvar.one.y1
.
.
&bvar.one.y7
&bvar.byte (This one differs)
(Note that it is not necessary that the fields inside of the structure
be bit fields for this to happen).
Note that setting bvar.y2 to 1 sets all bit fields to 4. This is
because they are all in a single unit, bit 2 is set (2 raised to the
power of 2 is 4), and they are in a structure rather than a union
(unlike sample code 1). However, since the address of bvar.byte
differs, it will be unaffected.
To work around the problem, place
unsigned byte:8;
inside a structure, as y0 - y7 are.
*********************************************************************/
typedef union bb
{
struct
{
unsigned y0:1;
unsigned y1:1;
unsigned y2:1;
unsigned y3:1;
unsigned y4:1;
unsigned y5:1;
unsigned y6:1;
unsigned y7:1;
}one;
unsigned byte:8;
}b;
b bvar;
void main( )
{
bvar.one.y2 = 1;
}
Additional reference words: 6.00 6.00a 6.00ax 2.50 bitfield