How do bit fields interplay with bits padding in C++

Question 1: are these two bits always the least significant bits of the underlying unsigned int? Or it is platform dependent?

Very platform dependent. The standard even has a note just to clarify how much:

[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 ]

You can't assume much of anything about the object layout of a bit field.

Question 2: Are those unused 30 bits always initialized to 0? What does the C++ standard say about it?

Your example has a simple aggregate, so we can enumerate the possible initializations. Specifying no initializer...

T t;

... will default initialize it, leaving the members with indeterminate value. On the other hand, if you specify empty braces...

T t{};

... the object will be aggregate initialized, and so the bit fields will be initialized with {} themselves, and set to zero. But that applies only to the members of the aggregate, which are the bit fields. It's not specified what value, if any, the padding bits take. So we cannot assume they will be initialized to zero.


Q1: Usually from low to hi (i.e. x is 1 << 0, y is 1 << 1, etc).

Q2: The value of the unused bits is undefined. On some compilers/platforms, stack initialised variables might be set to zero first (might!!), but don't count on it!! Heap allocated variables could be anything, so it's best to assume the bits are garbage. Using a slightly non standard anonymous struct buried in a union, you could do something like this to ensure the value of the bits:

union T {
 unsigned intval;
 struct { 
   unsigned x : 1;
   unsigned y : 1;
 };
}; 

T foo;
foo.intval = 0;