Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will {0, 0} initialize array in the struct?

Tags:

c++

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.

like image 601
exebook Avatar asked May 14 '15 23:05

exebook


1 Answers

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
}
like image 195
vsoftco Avatar answered Oct 18 '22 20:10

vsoftco