views:

91

answers:

2

Hello fellow SOers,

I'm asking this mainly out of curiousity. I am not really a C(++) Coder but to widen my horizon I try to dive in other areas every now and then. When doing this with C++ and some Winapi things, I encountered this guy:

#if defined(MIDL_PASS)
typedef struct _LARGE_INTEGER {
#else // MIDL_PASS
typedef union _LARGE_INTEGER {
    struct {
        DWORD LowPart;
        LONG HighPart;
    };
    struct {
        DWORD LowPart;
        LONG HighPart;
    } u;
#endif //MIDL_PASS
    LONGLONG QuadPart;
} LARGE_INTEGER;

So, the way I see it, depending on MIDL_PASS being set or not, this is either a very compact struct with only a LONGLONG in it, or the much more interesting case, this becomes a union.

In case this is a union, it still makes sense to me, to have two possibilites of access, once the LONGLONG in one chunk, and once the struct with Low and Highpart. So far so good.

But I cannot make any sense out of the fact that the struct is declared twice, identically. It seems they are both anonymous, but the latter one is available via "u".

Now to my question:

Why are the two structs defined (redundantly?), what is the purpose of the first one, if i cannot even access it, due to not being bound to any type / variable name.

Looking forward to your answers :)

greetings,

Tom

+1  A: 

You could directly access the LowPart and HighPart without having to go via the u member. As:

LARGE_INTEGER x;
x.HighPart = 42;

(Need to look up though if unnamed structs can be union members in Standard C.)

dirkgently
Cool, but then why bother having this redundancy at all? I don't really comprehend why this almost identical struct is there twice.
Tom
To make it portable.
dirkgently
+4  A: 

Microsoft provides anonymous structs as an extension (their example shows one struct inside another struct, but a struct in a union is similar). If you don't mind non-portable code based on their extension, you can use things like:

LARGE_INTEGER a;
a.LowPart = 1;

but if you want portable code, you need:

a.u.LowPart = 1;

The union lets you use either.

Jerry Coffin
okay, now that makes a lot of sense, thanks :D
Tom