C++中允许无名结构体的存在,例如下面的方式:
struct {
int a;
int d;
} foo;
在使用时一定要采用上面的方式来定义变量,即在定义无名结构体是即定义对象,原因就不用说了。
最近在查看 _LARGE_INTEGER 结构体时发现他的定义比较奇怪,原型为:
#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;
其实上面的这个定义本身就是一个条件编译,可以分解为如下:
1)如果宏定义了MIDL_PASS
typedef struct _LARGE_INTEGER {
LONGLONG QuadPart;
} LARGE_INTEGER;
对于此种情况没有什么疑义,再次不做解释了
2)如果没有宏定义MIDL_PASStypedef union _LARGE_INTEGER {
struct {
DWORD LowPart;
LONG HighPart;
};
struct {
DWORD LowPart;
LONG HighPart;
} u;
LONGLONG QuadPart;
} LARGE_INTEGER;
对于这种情况下的结构体访问方式,分为如下两种,LARGER_INTEGER li;
(1)
li.u.LowPart = 1;
li.u.HighPart=2;
这种情况相信大家都没有疑义吧。
(2)
li.LowPart = 1;
li.HighPart = 2;
对于这种情况,就有点难理解了,但从网上查到下面的内容:
For compatibility with other compilers, GCC allows you to define a structure or union that contains, as fields,
structures and unions without names. For example:
struct {
int a;
union {
int b;
float c;
};
int d;
} foo;
In this example, the user would be able to access members of the unnamed union with code like `foo.b'.
意思大概就是说为了兼容性,GCC编译器可以定义一个包含无名结构体或无名共用体的结构体或共用体,在上面这个例子里,可以通过 foo.b访问无名共用体中的成员变量。
这个是GCC的一些解释,相信其他编译器也采用了类似的方式!
Note that only unnamed structs and unions are allowed, you may not have, for example, an unnamed `int'.
You must never create such structures that cause ambiguous field definitions. For example, this structure:
struct {
int a;
struct {
int a;
};
} foo;
It is ambiguous which `a' is being referred to with `foo.a'. Such constructs are not supported and must be avoided. In the future, such constructs may be detected and treated as compilation errors.
Unless `-fms-extensions' is used, the unnamed field must be a structure or union definition without a tag (for example, `struct { int
a; };'). If `-fms-extensions' is used, the field may also be a definition with a tag such as `struct foo { int a; };', a reference to
a; };'). If `-fms-extensions' is used, the field may also be a definition with a tag such as `struct foo { int a; };', a reference to
a previously defined structure or union such as `struct foo;', or a reference to a `typedef' name for a previously defined structure or
union type.