实际使用零点
我对C没有完全确定,但C ++允许0长度的未命名位字段。 例如:
struct X
{
int : 0;
};
在冰毒犯罪的答案后编辑了这个例子
编辑:好的,感谢目前的答案,我现在知道理论的目的。 但问题是关于实际用途,所以他们仍然拥有:)
您使用零长度位域作为一种拙劣的方式让编译器布局结构以匹配某些外部需求,无论是其他编译器还是体系结构的布局概念(跨平台数据结构,例如二进制文件格式)或比特级标准的要求(网络数据包或指令操作码)。
NeXT将xnu内核从摩托罗拉68000(m68k)架构移植到i386架构是一个真实的例子。 NeXT有一个m68k版本的内核。 当他们将其移植到i386时,他们发现i386的对齐要求与m68k不同,m68k机器和i386机器不同意NeXT供应商特定BOOTP结构的布局。 为了使i386结构布局与m68k一致,他们添加了一个长度为零的未命名位域,以强制NV1
结构/ nv_U
结合为16位对齐。
以下是Mac OS X 10.6.5 xnu源代码的相关部分:
/* from xnu/bsd/netinet/bootp.h */
/*
* Bootstrap Protocol (BOOTP). RFC 951.
*/
/*
* HISTORY
*
* 14 May 1992 ? at NeXT
* Added correct padding to struct nextvend. This is
* needed for the i386 due to alignment differences wrt
* the m68k. Also adjusted the size of the array fields
* because the NeXT vendor area was overflowing the bootp
* packet.
*/
/* . . . */
struct nextvend {
u_char nv_magic[4]; /* Magic number for vendor specificity */
u_char nv_version; /* NeXT protocol version */
/*
* Round the beginning
* of the union to a 16
* bit boundary due to
* struct/union alignment
* on the m68k.
*/
unsigned short :0;
union {
u_char NV0[58];
struct {
u_char NV1_opcode; /* opcode - Version 1 */
u_char NV1_xid; /* transcation id */
u_char NV1_text[NVMAXTEXT]; /* text */
u_char NV1_null; /* null terminator */
} NV1;
} nv_U;
};
标准(9.6 / 2)只允许0长度位域作为特殊情况 :
作为特殊情况,宽度为零的未命名比特字段指定分配单元边界处下一个比特字段的对齐。 只有在声明一个未命名的比特字段时,常量表达式可以是一个等于零的值 。
唯一的用处在这个引用中描述,尽管我从来没有在实际的代码中遇到它。
为了记录,我只是在VS 2010下尝试了以下代码:
struct X {
int i : 3, j : 5;
};
struct Y {
int i : 3, : 0, j : 5; // nice syntax huh ?
};
int main()
{
std::cout << sizeof(X) << " - " << sizeof(Y) << std::endl;
}
我的机器上的输出确实是: 4 - 8
。
struct X { int : 0; };
在C中是未定义的行为
见(强调我的):
(C99,6.7.2.1p2)“struct-or-union-specifier中的struct-declaration-list的存在在一个翻译单元中声明一个新类型。struct-declaration-list是一个声明的序列结构体或联合体的成员如果struct-declaration-list不包含任何指定成员,则行为是未定义的 “
(C11有相同的措词。)
您可以使用宽度为0
的未命名位域,但如果结构中没有其他指定成员,则不能使用。
例如:
struct W { int a:1; int :0; }; // OK
struct X { int :0; }; // Undefined Behavior
顺便提一下第二个声明, gcc
发布了一个诊断(C标准没有要求)和-pedantic
。
另一方面:
struct X { int :0; };
在GNU C中定义。如果条件为真,则例如由Linux内核( include/linux/bug.h
)使用以下宏来强制编译错误:
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
链接地址: http://www.djcxy.com/p/12771.html