Bitfield assignment - is it safe?

1k views Asked by At

I have a bunch of properties crammed in a bitfield to save on space:

struct Flags {
    uint access : 2;
    uint status : 2;
    uint isEnabled : 1;
    uint isDeletable: 1;
    ...
};

Then I have a static Flags defaultFlags which is initialized on program startup. My main question is whether it is safe to flags = defaultFlags; in the object constructor, in order to eliminate the 20 lines for assigning each field individually?

Also, I was wondering what about serialization? According to the compiler, Flags is 4 bytes, can I serialize that as a 32bit unsigned integer and desterilize it as such without any data corruption?

1

There are 1 answers

0
Columbo On BEST ANSWER

My main question is whether it is safe to flags = defaultFlags; in the object constructor, in order to eliminate the 20 lines for assigning each field individually?

Yes. The implicitly defined copy constructor for Flags will assign each Bitfield appropriately. [class.copy]/15:

Each base or non-static data member is copied/moved in the manner appropriate to its type:

  • if the member is an array, [..]
  • if a member m has rvalue reference type T&& [..]
  • otherwise, the base or member is direct-initialized with the corresponding
    base or member of x.

can I serialize that as a 32bit unsigned integer and desterilize it as such without any data corruption?

If you write and read the file on the same machine with the same compiled program, yes. The layout might be different on other compilers or architectures though, the standard doesn't impose any fixed requirements in that respect. [class.bit]/1:

Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined. Bit-fields are packed into some addressable allocation unit. [ Note: Bit-fields straddle allocation units on some machines and not on others. Bit-fields are assigned right-to-left on some machines, left-to-right on others. — end note ]

If you write it into a char array of size sizeof Field, write that into a file and extract it from there again, copying it back into a Field object should thus give you the same values. [basic.types]/2 (emphasis mine):

For any object (other than a base-class subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes (1.7) making up the object can be copied into an array of char or unsigned char. If the content of the array of char or unsigned char is copied back into the object, the object shall subsequently hold its original value.

However, as pointed out in the comments, full portability (and reasonable efficiency) can be achieved using bitmasks.