Practical Use of Zero

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 :)


    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 .


    struct X { int : 0; };
    

    is undefined behavior in C.

    See (emphasis mine):

    (C99, 6.7.2.1p2) "The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type, within a translation unit. The struct-declaration-list is a sequence of declarations for the members of the structure or union. If the struct-declaration-list contains no named members, the behavior is undefined "

    (C11 has the same wording.)

    You can use an unnamed bit-field with 0 width but not if there is no other named member in the structure.

    For example:

    struct W { int a:1; int :0; };  // OK
    struct X { int :0; };           // Undefined Behavior
    

    By the way for the second declaration, gcc issues a diagnostic (not required by the C Standard) with -pedantic .

    On the other hand:

     struct X { int :0; };
    

    is defined in GNU C. It is used for example by the Linux kernel ( include/linux/bug.h ) to force a compilation error using the following macro if the condition is true:

    #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
    
    链接地址: http://www.djcxy.com/p/12772.html

    上一篇: 你最喜欢的C编程技巧是什么?

    下一篇: 实际使用零点