What is the best way to initialize a bitfield struct in C++?

13,640

Solution 1

You could always do this in your constructor:

memset(&bflag, 0, sizeof bflag);

Solution 2

Union the bitfield struct with something easier to initialize to 0.

Solution 3

You could use a union, although that would add an extra level of indirection when accessing the fields:

class Big {
    union {
        struct {
            unsigned int field1 : 1;
            ...
        } fields;
        unsigned int all_fields;
    };
    ...
};

Big::Big()
  : all_fields(0),
    ...
{
    ...
}

MSVC allows anonymous structs inside of unions (see, e.g. the definition of D3DMATRIX in <d3d9.h>), but this is a non-standard C++ extension which you should avoid using if you can.

Solution 4

BTW C++20 supports initializing the bitfields in the class definition e.g.

class ... {
   int foo : 1 {};
}

gcc with -std=c++2a to enable

Solution 5

Your use of a function-like initializer (marked "Can I zero bflag here?") is 100% sufficient to initialize your POD struct with 0 values.

Unless you know your compiler is broken in this regard, doing any additional initialization of those members is initializing it twice for no benefit.

EDIT: Just for 'fun' I just checked this with VS2005, VS2008, GCC 3.4.4, GCC 4.2, and Borland C++ 5.5.1 ... only Borland C++ 5.5.1 gets it wrong.

And I say 'wrong' because it seems to me that 8.5 and 8.5.1 of the standard imply that the function-like initializer should zero-init the POD struct.

Share:
13,640
Ben Martin
Author by

Ben Martin

Developer at The Mathworks.

Updated on June 04, 2022

Comments

  • Ben Martin
    Ben Martin almost 2 years

    In C++, I have a class which contains an anonymous bitfield struct. I want to initialize it to zero without having to manually write out all fields.

    I can imagine putting the initialization in three places:

    1. Create a constructor in the bitfield
    2. Zero out in the initializer list of the constructor for the containing class
    3. Zero out in the body of the constructor for the containing class

    This bitfield has many fields, and I'd rather not list them all.

    For example see the following code:

    class Big {
        public:
            Big();
    
            // Bitfield struct
            struct bflag_struct {
                unsigned int field1 : 1;
                unsigned int field2 : 2;
                unsigned int field3 : 1;
                // ...
                unsigned int field20 : 1;
                // bflag_struct(); <--- Here?
            } bflag;
    
            unsigned int integer_member;
            Big         *pointer_member;
    }
    
    Big::Big()
      : bflag(),             // <--- Can I zero bflag here?
        integer_member(0),
        pointer_member(NULL)
    {
        // Or here?
    }
    

    Is one of these preferable? Or is there something else I'm missing?

    Edit: Based on the accepted answer below (by Ferruccio) I settled on this solution:

    class Big {
        // ...
    
        struct bflag_struct {
            unsigned int field 1 : 1;
            // ...
            bflag_struct() { memset(this, 0, sizeof *this); };
        }
    
        // ...
    }
    
    • Paul Sanders
      Paul Sanders about 2 years
      memset(this, 0, sizeof *this); ooooooo POD types only!
  • Ben Martin
    Ben Martin about 15 years
    This is legacy code that I'm converting from calloc to new. The bitfield can occur hundreds of thousands of times, so memory is cruicial.
  • Larry Gritz
    Larry Gritz about 15 years
    I believe it's unportable (in the sense that different architectures may store the bits in different locations), but how is it inefficient?
  • Ben Martin
    Ben Martin about 15 years
    I believe the processor has to do a lot more work to retrieve a bit within a bit field than to use a bool. For our application, loosing speed to save memory is worthwhile.
  • Ben Martin
    Ben Martin about 15 years
    I'm afraid I need to be very sure that the data is zeroed for safety critical reasons and we compile on a number of platforms. Thanks for testing.
  • Ferruccio
    Ferruccio almost 7 years
    Bit fields are completely portable. If you start making assumptions about how the compiler is going to allocate bits then you're introducing undefined behavior. Also, the whole point of bit fields is to tell the compiler that, in this particular case, space efficiency is more important than time efficiency.
  • celticminstrel
    celticminstrel over 4 years
    To be clear, it's only unportable if you're directly serializing the memory to disk with the expectation that another computer (possibly running a different platform!) will deserialize it to the exact same representation. But your serialization shouldn't be a memory dump anyway, so...
  • maxschlepzig
    maxschlepzig over 2 years
    They are memory efficient. So if you are targeting something like a 8 bit microcontroller and you are short on RAM bitfields are a natural fit.