C++ Logo

liaison

Advanced search

Re: [wg14/wg21 liaison] [SC22WG14.21755] N2900 Initialization with {} and potential semantic divergence from C++ for new-to-C syntax

From: Jens Maurer <Jens.Maurer_at_[hidden]>
Date: Sat, 5 Mar 2022 22:16:25 +0100
On 05/03/2022 18.19, JeanHeyd Meneide via Liaison wrote:
> Coming back to this thread, it looks like C++ *does* zero-initialize the padding of its bits when it uses the syntax = {};. Wording from [dcl.init.general], paragraph 6 (http://eel.is/c++draft/dcl.init.general#6 <http://eel.is/c++draft/dcl.init.general#6>):
>
> 6 <http://eel.is/c++draft/dcl.init.general#6> To /zero-initialize/ <http://eel.is/c++draft/dcl.init.general#def:zero-initialization> an object or reference of type T means:
>
> *
> (6.1) <http://eel.is/c++draft/dcl.init.general#6.1>
> if T is a scalar type ([basic.types.general] <http://eel.is/c++draft/basic.types.general#term.scalar.type>), the object is initialized to the value obtained by converting the integer literal 0 (zero) to T;84 <http://eel.is/c++draft/dcl.init.general#footnote-84>
> *
> (6.2) <http://eel.is/c++draft/dcl.init.general#6.2>
> if T is a (possibly cv-qualified) non-union class type, its padding bits ([basic.types.general] <http://eel.is/c++draft/basic.types.general#term.padding.bits>) are initialized to zero bits and each non-static data member, each non-virtual base class subobject, and, if the object is not a base class subobject, each virtual base class subobject is zero-initialized;
> *
> (6.3) <http://eel.is/c++draft/dcl.init.general#6.3>
> if T is a (possibly cv-qualified) union type, its padding bits ([basic.types.general] <http://eel.is/c++draft/basic.types.general#term.padding.bits>) are initialized to zero bits and the object's first non-static named data member is zero-initialized;
> *
> (6.4) <http://eel.is/c++draft/dcl.init.general#6.4>
> if T is an array type, each element is zero-initialized;
> *
> (6.5) <http://eel.is/c++draft/dcl.init.general#6.5>
> if T is a reference type, no initialization is performed.
>
> 6.2 and 6.3 make it pretty clear that when we use
>
> T x = {};
>
> we get padding bits that are meant to be zero here, not indeterminate. This also matches up with the wording in [dcl.init.aggr], though I am unsure if "default member initializer" maps to zero-initialize or default-initialize. Am I missing something? Am I interpreting the C++ wording incorrectly? It seems like C++ had padding-set-to-0 all along?

You quoted the section about zero-initialization, which does set
(static) padding to zero bits. Why do you think that "T x = {}"
gets to that section at all?

My opinion:

For zero-initialization of unions, C++ should specify that excess bits
reserved for the object representation of other members are set to zero.
This is likely what happens anyway for a case like this:

union U {
  char c;
  float f;
};

static U u; // the unused bytes after u.c should be set to zero

(I note that there are situations where the current C++ wording appears
to require leaving some parts of a static variable entirely uninitialized;
that's likely a bug, see https://cplusplus.github.io/CWG/issues/2543.html ).

For "T x = {}" (maybe as an automatic variable), I note that C++ would
invoke a copy constructor for e.g. "return x", but that copy constructor
would perform effectively a memcpy of the entire union; see [class.copy.ctor] p15.
So, any zeroed padding would survive, unlike for structs, where padding
values are not guaranteed to survive a copy.

Jens

Received on 2022-03-05 21:16:31