Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Practical Use of Zero-Length Bitfields

Tags:

c++

c

bit-fields

I am not totally sure about C, but C++ allows unnamed bit-fields of 0 length. For example:

struct X {     int : 0; }; 
  • Question one: What practical uses of this can you think of?
  • Question two: What real-world practical uses (if any) are you aware of?

Edited the example after ice-crime's answer

Edit: OK, thanks to the current answers I now know the theoretical purpose. But the questions are about practical uses so they still hold :)

like image 908
Armen Tsirunyan Avatar asked Nov 28 '10 13:11

Armen Tsirunyan


People also ask

What are Bitfields What is the use of bit fields in a structure declaration?

These space-saving structure members are called bit fields, and their width in bits can be explicitly declared. Bit fields are used in programs that must force a data structure to correspond to a fixed hardware representation and are unlikely to be portable.

What is bit fields list its purposes?

Bit fields can be used to reduce memory consumption when a program requires a number of integer variables which always will have low values. For example, in many systems storing an integer value requires two bytes (16-bits) of memory; sometimes the values to be stored actually need only one or two bits.

Is array of bit fields allowed?

Arrays of bit fields, pointers to bit fields, and functions returning bit fields are not allowed. The optional declarator names the bit field. Bit fields can only be declared as part of a structure. The address-of operator (&) cannot be applied to bit-field components.

Can we use bit fields in Union?

Bit fields CANNOT be used in union.


2 Answers

You use a zero-length bitfield as a hacky way to get your compiler to lay out a structure to match some external requirement, be it another compiler's or architecture's notion of the layout (cross-platform data structures, such as in a binary file format) or a bit-level standard's requirements (network packets or instruction opcodes).

A real-world example is when NeXT ported the xnu kernel from the Motorola 68000 (m68k) architecture to the i386 architecture. NeXT had a working m68k version of their kernel. When they ported it to i386, they found that the i386's alignment requirements differed from the m68k's in such a way that an m68k machine and an i386 machine did not agree on the layout of the NeXT vendor-specific BOOTP structure. In order to make the i386 structure layout agree with the m68k, they added an unnamed bitfield of length zero to force the NV1 structure/nv_U union to be 16-bit aligned.

Here are the relevant parts from the Mac OS X 10.6.5 xnu source code:

/* 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; }; 
like image 69
Jeremy W. Sherman Avatar answered Sep 21 '22 11:09

Jeremy W. Sherman


The standard (9.6/2) only allows 0 length bit-fields as a special case :

As a special case, an unnamed bit-field with a width of zero specifies alignment of the next bit-field at an allocation unit boundary. Only when declaring an unnamed bit-field may the constant-expression be a value equal to zero.

The only use is described in this quote, although I've never encountered it in practical code yet.


For the record, I just tried the following code under 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; } 

The output on my machine is indeed : 4 - 8.

like image 29
icecrime Avatar answered Sep 23 '22 11:09

icecrime