零长度位域的实际应用

时间:2010-11-28 13:58:34

标签: c++ c bit-fields

我不完全确定C,但C ++允许未命名的0字段位字段。例如:

struct X
{
    int : 0;
};
  • 问题一:想到的这个实际用途是什么?
  • 问题二:您了解哪些实际用途(如果有)?

编辑 冰犯罪回答后的例子

编辑 好了,多亏了目前的答案,我现在知道了理论目的。但问题是关于实际用途,所以他们仍然坚持:)

5 个答案:

答案 0 :(得分:27)

使用零长度位域作为一种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;
};

答案 1 :(得分:20)

标准(9.6 / 2)仅允许0个长度的位字段作为特殊情况

  

作为一个特例,一个未命名的   宽度为零的位域   指定下一个的对齐方式   分配单元的位字段   边界。 仅在声明时   未命名的位字段可能是   constant-expression是一个值相等的值   为零

本引文中描述了唯一的用途,尽管我在实际代码中从未遇到过它。


为了记录,我刚刚在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

答案 2 :(得分:7)

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-pedantic发出诊断(C标准不要求)。

另一方面:

 struct X { int :0; };

在GNU C中定义。例如,Linux内核(include/linux/bug.h)用于在条件为真时使用以下宏强制编译错误:

#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))

答案 3 :(得分:6)

这是来自MSDN,并未标记为Microsoft Specific,因此我猜这是常见的C ++标准:

宽度为0的未命名位域强制将下一位字段与下一个类型边界对齐,其中type是成员的类型。

答案 4 :(得分:0)

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