[英]Practical Use of Zero-Length Bitfields
我不完全確定C,但C ++允許未命名的0字段位字段。 例如:
struct X
{
int : 0;
};
在冰犯罪的回答之后編輯了這個例子
編輯:好的,多虧了目前的答案,我現在知道了理論目的。 但問題是關於實際用途,所以他們仍然持有:)
使用零長度位域作為一種hacky方式,讓你的編譯器布局一個結構來匹配一些外部需求,無論是另一個編譯器或架構的布局概念(跨平台數據結構,如二進制文件格式) )或比特級標准的要求(網絡數據包或指令操作碼)。
一個真實的例子是NeXT將xnu內核從Motorola 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); }))
這是來自MSDN,並沒有標記為Microsoft Specific,所以我想這是常見的C ++標准:
寬度為0的未命名位域強制將下一位字段與下一個類型邊界對齊,其中type是成員的類型。
C11標准現在允許包含零長度位域。 以下是C委員會草案(N1570)的一個例子,我相信這是一個實際用法。
3.14內存位置
...
4.示例聲明為的結構struct { char a; int b:5, c:11, :0, d:8; struct { int ee:8; } e; }
包含四個獨立的存儲器位置:成員
a
和位字段d
和e.ee
是每個單獨的存儲器位置, 並且可以同時修改而不會相互干擾 。 位域b
和c
一起構成第四存儲器位置。 位域b
和c
不能同時修改,但b
和a
例如可以。
因此,在位域c
和d
之間包括零長度位域允許同時修改b
和d
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.