簡體   English   中英

零長度位域的實際應用

[英]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和位字段de.ee是每個單獨的存儲器位置, 並且可以同時修改而不會相互干擾 位域bc一起構成第四存儲器位置。 位域bc不能同時修改,但ba例如可以。

因此,在位域cd之間包括零長度位域允許同時修改bd

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM