I am not totally sure about C, but C++ allows unnamed bit-fields of 0 length. For example:
struct X { int : 0; };
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 :)
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.
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.
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.
Bit fields CANNOT be used in union.
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; };
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With