3

I'm trying to initialize a LARGE_INTEGER to 0 in a C++ library (C++03 to be exact). Previously, the initialization was:

static LARGE_INTEGER freq = { 0 };

Under MinGW it produced a warning:

missing initializer for member '_LARGE_INTEGER::::HighPart'

So I changed the initialization to the following in accordance with Can a union be initialized in the declaration?:

static LARGE_INTEGER freq = { .QuadPart = 0 };

I'm now testing under Visual Studio 2015, and its producing an error:

81  static LARGE_INTEGER freq = { .QuadPart = 0 };
82  if (freq.QuadPart == 0)
83  {
84      if (!QueryPerformanceFrequency(&freq))
85          throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed ..."));
86 }

hrtimer.cpp(81): error C2059: syntax error: '.'
hrtimer.cpp(81): error C2143: syntax error: missing ';' before '}'
hrtimer.cpp(82): error C2059: syntax error: 'if'
hrtimer.cpp(83): error C2143: syntax error: missing ';' before '{'
hrtimer.cpp(83): error C2447: '{': missing function header (old-style formal list?)
hrtimer.cpp(87): error C2059: syntax error: 'return'

How do I initialize a union to its largest member under the MSVC compiler?


Here is Microsoft's definiton of LARGE_INTEGER:

#if defined(MIDL_PASS)
typedef struct _LARGE_INTEGER {
#else // MIDL_PASS
typedef union _LARGE_INTEGER {
    struct {
        DWORD LowPart;
        LONG HighPart;
    } DUMMYSTRUCTNAME;
    struct {
        DWORD LowPart;
        LONG HighPart;
    } u;
#endif //MIDL_PASS
    LONGLONG QuadPart;
} LARGE_INTEGER;
Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • 2
    `{ .QuadPart = 0 };` is illegal in C++. Designated initializers are C-only. You link to a [tag:c] question. – M.M Jul 26 '15 at 14:37
  • @MattMcNabb if you name every member before (not sure about after) it is legal I believe. – RamblingMad Jul 26 '15 at 14:39
  • @CoffeeandCode no, it's a syntax error – M.M Jul 26 '15 at 14:39
  • Thanks Matt. I was not aware there was a difference. So much for that C/C++ compatibility/superset thing... Do you know how I can initialize this beast properly under GCC and MSVC? – jww Jul 26 '15 at 14:40
  • @MattMcNabb oh, GCC was letting me use C99 extensions. My bad. – RamblingMad Jul 26 '15 at 14:41
  • @jww what is your use case? Unions may only have one active member at a time in C++ , so they should be 'initialized' by assigning to the member you want to set active (unless it's the first member in which case you can use the braced initialization). – M.M Jul 26 '15 at 14:45
  • 32-bit and 64-bit operating systems (so `lowPart/highPart/quadPart` will be used eventually); GCC and Windows compilers. Its static, so its needs to be initialized when declared. – jww Jul 26 '15 at 15:04
  • I guess from this struct definition that the program will use union aliasing,which is undefined behaviour in standard C++; presumably MSVC defines it (and the other windows compilers follow suit in order to be accepted by windows users) – M.M Jul 26 '15 at 15:09
  • 1
    Since it's static, why initialize it at all? – Johnny Cage Jul 26 '15 at 15:09

1 Answers1

3

{ .QuadPart = 0 }; is illegal in C++. Designated initializers are C-only, however, they are supported from C++20. You link to a question.

In C++03 [dcl.init.aggr]/15: (your union is an aggregate):

When a union is initialized with a brace-enclosed initializer, the braces shall only contain an initializer for the first member of the union.

So, it is not possible to initialize "the largest member" unless that member is the first member.


The MinGW warning is bogus. g++ used to issue warnings for = { 0 };, however that is a common idiom, so they fixed it to not do that any more. I guess you have a slightly old version.

In your code, = { 0 }; should initialize DUMMYSTRUCTNAME to {0, 0}. According to this, all members of your union are 64-bit so in this particular case, you did actually initialize the largest member.

Pavel P
  • 15,789
  • 11
  • 79
  • 128
M.M
  • 138,810
  • 21
  • 208
  • 365
  • I think the warning was issued on MinGW, 32-bit (not 64-bit). Will `{0,0}` work everywhere? Are the compilers smart enough to know to use `lowPart` and `highPart` in this case (which effectively sets `quadPart` to 0)? – jww Jul 26 '15 at 15:06
  • 1
    @jww no, that's illegal. `{0}` is correct . Perhaps `{ {0, 0} }` would get rid of the bogus warning. (or as Johnny Cage points out, no iniitalizer at all is equivalent to this case, for `static` objects) – M.M Jul 26 '15 at 15:07
  • In case you are unaware, mingw-w64 comes in 32bit and 64bit builds, and is pretty up to date (I think g++ 5.1.0) – M.M Jul 26 '15 at 15:08
  • I found the mingw-32 download, but I don't recall finding the mingw-64 on their site. So I test under Cygwin-32, Cygwin-64 and MinGW-32. I'm less concerned about what they are providing because I can usually get the latest compiler from Fedora. I test under Cygwin and MinGW for the cross-platform assurances. – jww Jul 26 '15 at 16:28
  • FYI, designated initializers `{ .QuadPart = 0 }` are ok in C++20 – Pavel P Dec 24 '22 at 14:51