Does C++ support a language construct that will allow us to initialize an object and all its padding fields to zero. I found some encouraging wording in cppreference.com about zero-initialization that suggests that on some conditions, the padding bytes will also be zeroed out.
Quoting from cppreference.com: zero-initialization
Zero initialization is performed in the following situations:
- As part of value-initialization sequence for non-class types and for members of value-initialized class types that have no constructors, including value initialization of elements of aggregates for which no initializers are provided.
The effects of zero initialization are:
- If T is a scalar type, the object's initial value is the integral constant zero explicitly converted to T.
- If T is an non-union class type, all base classes and non-static data members are zero-initialized, and all padding is initialized to zero bits. The constructors, if any, are ignored.
- ...
One will find references to zero-initialization in value-initialization, aggregate-initialization and list-initialization.
I tested using fairly latest GCC and clang C++ compilers, and their behavior seems divergent.
Frankly, I tried hard to parse these rules, especially given that the divergent compiler behavior, I could not figure out how to interpret these rules correctly.
See code here (min C++11 is required). And here are the results:
Given: Foo
struct Foo
{
char x;
int y;
char z;
};
Construct | g++ | clang++ |
---|---|---|
Foo() | x:[----][0x42][0x43][0x44],v: 0 |
x:[----][----][----][----],v: 0 |
y:[----][----][----][----],v: 0 |
y:[----][----][----][----],v: 0 |
|
z:[----][0x4A][0x4B][0x4C],v: 0 |
z:[----][----][----][----],v: 0 |
|
Foo{} | x:[----][----][----][----],v: 0 |
x:[----][0x42][0x43][0x44],v: 0 |
y:[----][----][----][----],v: 0 |
y:[----][----][----][----],v: 0 |
|
z:[----][----][----][----],v: 0 |
z:[----][0x4A][0x4B][0x4C],v: 0 |
Here [----]
represents a byte containing all bits 0, and [0x..]
is garbage value.
As you can see the compiler outputs indicate that padding is not initialized. Both Foo()
and Foo{}
are value-initializations. In addition Foo{}
is an aggregate-initialization, with missing initializers. Why isn't the zero-initialization rule getting triggered? Why isn't padding rule getting triggered?
I already understand that relying on padding bytes to be zero is not a good idea or may even be undefined behavior, but I think that is besides the point of this question.
- Question 1: Does the standard provide a way to reliably initialize the padding bytes?
- Question 2: Also see: does c initialize structure padding. Is it applicable?
- Question 3: Are these compilers compliant with the standards?
- Question 4: What is the explanation of the compiler's clearly divergent behavior?
-O3
defined for the compilers. The compiler can do almost anything as long as there is no observable difference in behavior. Is padding observable. – Minter-ftrivial-auto-var-init=choice
flag – Impeccable