10

In this code, will all 100 items of C.B be initialized to zero?

struct A { int B[100]; int D; };
A C = {0, 0};

It seems to work, but memory could have just been empty in advance.

viraptor
  • 33,322
  • 10
  • 107
  • 191
exebook
  • 32,014
  • 33
  • 141
  • 226
  • This is not a duplicate, can you see the difference between initializing array and struct? – exebook May 14 '15 at 23:39
  • `A C = {0};` performs value initialization of an aggregate, hence it value-initializes each member. So indeed the member array is indeed zeroed. – vsoftco May 14 '15 at 23:40
  • @vsoftco, should it be {{0}} instead? – exebook May 14 '15 at 23:41
  • There are some rules (I cannot remember them from the top of my head) that say that you can elide the braces for aggregates. Here: http://en.cppreference.com/w/cpp/language/aggregate_initialization *"If the aggregate initialization uses the form with the equal sign (T a = {args..}), (until C++14) the braces around the nested initializer lists may be elided (omitted),..."* – vsoftco May 14 '15 at 23:41
  • Now that we see it this is indeed a interesting question! Is there a way to remove the dup flag from it? – Denilson Amorim May 14 '15 at 23:41
  • 1
    By the way there's a answer here http://stackoverflow.com/questions/11152160/initializing-a-struct-to-0 But I still think this question should be opened again. – Denilson Amorim May 14 '15 at 23:43
  • So your case is a combination of the 2: aggregate initialization and value initialization. – vsoftco May 14 '15 at 23:44
  • @thelink2012: You are linking to question tagged for `C`. This question is tagged `C++` and uses `aggregate initialization` that is explained in the link by vsoftco. An array and a struct are both aggregates. Anyways in C++ you would use `A C = {};` or just `A C{};` from C++11. – Jesse Good May 14 '15 at 23:50
  • @JesseGood Thus why I asked you guys to open the question again ;) The question is not a dup and is interesting. – Denilson Amorim May 15 '15 at 00:00
  • @thelink2012: Well, the original question was changed, but anyways they all fall under `aggregate initialization`. – Jesse Good May 15 '15 at 00:06

1 Answers1

5

The line

A C = {0, 0}; 

Performs value initialization of the aggregate A. According to the standard, the braces can be omitted for aggregate initialization:

8.5.1 Aggregates[dcl.init.aggr]/12

Braces can be elided in an initializer-list as follows. If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the members of a subaggregate; it is erroneous for there to be more initializer-clauses than members. If, however, the initializer-list for a sub- aggregate does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the members of the subaggregate; any remaining initializer-clauses are left to initialize the next member of the aggregate of which the current subaggregate is a member.

[Example:

 float y[4][3] = {
   { 1, 3, 5 },
   { 2, 4, 6 },
   { 3, 5, 7 }, }; 

is a completely-braced initialization: 1, 3, and 5 initialize the first row of the array y[0], namely y[0][0], y[0][1], and y[0][2]. Likewise the next two lines initialize y[1] and y[2]. The initializer ends early and therefore y[3]'s elements are initialized as if explicitly initialized with an expression of the form float(), that is, are initialized with 0.0. In the following example, braces in the initializer-list are elided; however the initializer-list has the same effect as the completely-braced initializer-list of the above example,

 float y[4][3] = {
   1, 3, 5, 2, 4, 6, 3, 5, 7 }; 

The initializer for y begins with a left brace, but the one for y[0] does not, therefore three elements from the list are used. Likewise the next three are taken successively for y[1] and y[2]. — end example ]

Next

8.5.1 Aggregates[dcl.init.aggr]/7

If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from its brace-or-equal-initializer or, if there is no brace-or-equal- initializer, from an empty initializer list.

In your case, this mean that the first 0 is assigned to B[0] and the second 0 is assigned to B[1]. According then to 8.5.1/7, the rest of the elements are value-initialized.

However, for clarity in this case, you should use A C = {{0}, 0};, or, better

A C{}; // or A C = {};

The only thing that worries me a bit is the g++ warning (-Wextra):

warning: missing initializer for member 'main()::A::D' [-Wmissing-field-initializers] A C {0,0};

But according to my interpretation of the standard above, you should be OK and D should have been initialized. I even tested it with some placement new, and the result is as expected

#include <iostream>

int main()
{
    struct A { int B[100]; int D;};
    A memory{};
    memory.D = 42; 
    std::cout << memory.D << std::endl;

    // let's place something an A at the location of memory
    A* foo = new (&memory) A{0,0}; 
    // line below outputs 0, so D is erased; not the case if A* foo = new (&memory) A; 
    std::cout << memory.D << std::endl; // outputs 0
}
Peter O.
  • 32,158
  • 14
  • 82
  • 96
vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • 1
    I already edited the question, so it is not {0} any more, but {0,0}. This way it makes my actual consideration more clear. – exebook May 14 '15 at 23:51