Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pre C++20 bit field zero-initialization

Question is in the code below, asking whether using value initialization syntax as shown would mean zero-initialized or uninitialized for the individual bit-field members:

struct S { // S is POD
   int a : 3;
   int b : 1;
};

S s1;
S s2{};

s1.a; // uninitialized (ok, we understand this)
s1.b; //  "

s2.a; // zero or junk?
s2.b; //  "

Here is a refresher for bit-fields: https://en.cppreference.com/w/cpp/language/bit_field

Creating zeroing constructors for structs with many bit fields is typically done with an ugly memset in legacy code since repeating the name of each bitfield member with value-init syntax in constructor initializer list yields unmanageable code. This is done even if the struct is a POD for good measure. Would like to eliminate that if possible in C++11 (default-member initialization syntax is not available for bit fields until C++20 unfortunately). Does C++11 guarantee zero-initialization for this with {}-init syntax?

like image 382
Nick Avatar asked Aug 23 '18 15:08

Nick


People also ask

Does default constructor zero initialize?

Implicitly defined (by the compiler) default constructor of a class does not initialize members of built-in types.

Does C++ initialize variables to zero?

Unlike some programming languages, C/C++ does not initialize most variables to a given value (such as zero) automatically. Thus when a variable is assigned a memory location by the compiler, the default value of that variable is whatever (garbage) value happens to already be in that memory location!

Does New initialize memory 0?

Yes. That's kind of my point. If you make a new variable and see that's it's zero, you can't straight away assume that something within your program has set it to zero. Since most memory comes ready-zeroed, it's probably still uninitialised.

Is std :: array zero initialized?

std::array::array For elements of a class type this means that their default constructor is called. For elements of fundamental types, they are left uninitialized (unless the array object has static storage, in which case they are zero-initialized).


1 Answers

Does C++11 guarantee zero-initialization for this with {}-init syntax?

Yes.


struct S {
   int a : 3;
   int b : 1;
};

Per [dcl.init.aggr]/1, S is an aggregate.

An aggregate is an array or a class ([class]) with
(1.1) no user-declared or inherited constructors ([class.ctor]),
(1.2) no private or protected non-static data members ([class.access]),
(1.3) no virtual functions ([class.virtual]), and
(1.4) no virtual, private, or protected base classes ([class.mi]).

[ Note: Aggregate initialization does not allow accessing protected and private base class' members or constructors. — end note ]

The rest of [dcl.init.aggr] defines how an aggregate is initialized, and no mention is made about bit-fields; they are thus initialized following the same rules as other aggregate classes.

The meaning of S s{} is defined in [dcl.init.aggr]/5:

For a non-union aggregate, each element that is not an explicitly initialized element is initialized as follows:
...
(5.2) Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list ([dcl.init.list]).

So, let's see [dcl.init.list]/3... and it is huge! Checking point after point, we find [dcl.init.list]/3.11:

(3.11) Otherwise, if the initializer list has no elements, the object is value-initialized.

Which, for a scalar type, means zero-initialization :)

Does C++11 guarantee zero-initialization for this with {}-init syntax?

Yes.

like image 103
YSC Avatar answered Oct 02 '22 21:10

YSC