BUG: Array of Unnamed Union Does Not Initialize Correctly

Last reviewed: July 22, 1997
Article ID: Q126843
1.00 1.50 1.51 1.52 WINDOWS kbtool kbbuglist

The information in this article applies to:

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

        - Microsoft Visual C++ for Windows, versions 1.0, 1.5, 1.51 and
          1.52
    

SYMPTOMS

Structures that include unnamed unions do not get initialized correctly in C++ code.

CAUSE

The compiler inserts an extra block of data equal to the size of the union after each object. Therefore, every other initialized object will apparently be skipped. See the sample output in SAMPLE 1 below in the MORE INFORMATION section.

RESOLUTION

This problem can be worked around using one of the following methods:

  1. Named unions instead of unnamed unions.

    - or -

  2. Define constructors for the structure.

More detailed information is provided in sample code SAMPLE 2, found below.

STATUS

Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. We are researching this bug and will post new information here in the Microsoft Knowledge Base as it becomes available.

MORE INFORMATION

The following sample code SAMPLE 1 reproduces the problem. Use SAMPLE 2 to work around the problem. Both samples should be .CPP applications.

Sample Code

SAMPLE 1 :

/* Compile options needed: none.
*/

#include <stdio.h>

struct MyStruct {
  union {
     char c[8];
     struct {
        unsigned long uL1, uL2;
       };
    };
};

MyStruct ms[] = {

  {"Z000"},
  {"Z001"},
  {"Z002"},
  {"Z003"},
  {"Z004"}
};

void main()
{
  for ( int i=0; i<=4; i++ )
   printf("ms[%d] = %s\n",i,ms[i].c );
}

Output :

ms[0] = Z000 ms[1] = ms[2] = Z001 ms[3] = ms[4] = Z002

SAMPLE 2 :

/* Compile options needed: none
*/

#include <stdio.h>

// Define CASE1 or CASE2 here.

#ifdef CASE1 struct MyStruct {
  union {
     char c[8];
     struct {
        unsigned long uL1, uL2;
     };
  } t;  // Name the union here.
}; #endif

#ifdef CASE2

#include <string.h>

struct MyStruct {
  union {
     char c[8];
     struct {
        unsigned long uL1, uL2;
     };
  };
  MyStruct(unsigned long l1, unsigned long l2) {
      uL1 = l1;
      uL2 = l2;
  }             // Constructor
  MyStruct(char *lpz) {
      strcpy(c, lpz);
  }             // Constructor
  MyStruct(){}  // Constructor
}; #endif

MyStruct ms[] = {

  {"Z000"},
  {"Z001"},
  {"Z002"},
  {"Z003"},
  {"Z004"}
};

void main()
{ #ifdef CASE1
   for ( int i=0; i<=4; i++ )
     printf("ms[%d] = %s\n",i,ms[i].t.c );
#endif

#ifdef CASE2

   for ( int i=0; i<=4; i++ )
     printf("ms[%d] = %s\n",i,ms[i].c );
#endif }

Output :

ms[0] = Z000 ms[1] = Z001 ms[2] = Z002 ms[3] = Z003 ms[4] = Z004


Additional reference words: CPP nameless 8.00 8.00c 1.00 1.50 1.51 1.52
KBCategory: kbtool kbbuglist
KBSubCategory: CPPIss
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 22, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.