84

It is well known that missing initializers for an array of scalars are defaulted to zero.

int A[5]; // Entries remain uninitialized
int B[5]= { 0 }; // All entries set to zero

But is this (below) guaranteed ?

int C[5]= { }; // All entries set to zero
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 3
    [Read about aggregate initialization](http://en.cppreference.com/w/cpp/language/aggregate_initialization). – Some programmer dude Aug 11 '16 at 09:33
  • @JoachimPileborg: I already read about array initializers. This particular explanation is more obscure than anything else. –  Aug 11 '16 at 09:37
  • @M.M: tag as duplicate, then. –  Aug 11 '16 at 09:41
  • 1
    well, similar, http://stackoverflow.com/questions/38840514/ – M.M Aug 11 '16 at 09:42
  • 1
    @mm: mh, my question is specifically about empty braces, which seem to never appear in examples. One (me) may be tempted to believe that they amount to no braces at all. That's what I needed to check. –  Aug 11 '16 at 09:47
  • OK. The `B` and `C` in your question are actually covered by the same rule , any entries not given initializers are zero-initialized – M.M Aug 11 '16 at 09:48
  • 1
    This is why [`{0}` is confusing/misleading](https://stackoverflow.com/q/14797810/560648). – Lightness Races in Orbit Mar 23 '18 at 00:33

4 Answers4

100

The empty braced initialisation performs aggregation-initialization of the array: this leads to zero-initialization of the int elements.

Yes, this is guaranteed.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 1
    `int C[5]` is not a class type, so value-initialization is not performed, aggregate initialization is performed. – Holt Aug 11 '16 at 09:40
  • 1
    @Holt: and ? Does this change the conclusion ? –  Aug 11 '16 at 09:49
  • 2
    @Holt whether it's a class type or not does not impact whether aggregate initialization is performed. All array initialization is aggregate initialization. Also, aggregate initialization is defined such that members with no initializer are value-initialized (which is equivalent to zero-initialization, for `int`) – M.M Aug 11 '16 at 09:52
  • @M.M Well, the standard says *"[...] and T is a class type with a default constructor [...] Otherwise, if T is an aggregate type [...]"*, so whether it's a class type or not matters (I am not talking about `int` here, I am talking about `int[5]`). Since here `T` is `int[5]`, `T` is an array type, not a class type, so aggregate initialization is performed, not value-initialization. The elements of `C` will then be value-initialized, but the first thing that is "done" is aggregate-initialization. I was not pointing out the conclusion, simply the wording of the answer. – Holt Aug 11 '16 at 09:59
  • 1
    @Holt: decrypting the C++ standard is an endless game. –  Aug 11 '16 at 10:00
  • @Holt if `T` is an array type, it is not a class type – M.M Aug 11 '16 at 10:00
  • @M.M Yes, that's exactly what I said in my comment. – Holt Aug 11 '16 at 10:00
  • @Holt this question is only about array initialization so I'm not sure where you're coming from – M.M Aug 11 '16 at 10:01
  • 1
    @M.M `int C[5] = {}` is [list initialization](http://en.cppreference.com/w/cpp/language/list_initialization) with `T = int[5]`, by the standard this will performs aggregate initialization, but the **initial answer** was mentioning value-initialization, which would be the case if `T` was a class type with default constructor. I just pointed out that what was happening here was aggregate initialization, not value-initialization. – Holt Aug 11 '16 at 10:02
  • @M.M You and I are telling the same thing since the first comment, you probably did not see the original answer which is why you are confusing the meaning of my comments (just look at the edit revision). – Holt Aug 11 '16 at 10:03
  • Indeed I did edit it to use better terminology, following the useful comments from @Holt. – Bathsheba Aug 11 '16 at 10:10
  • 1
    I am always wondering how people know that kind of stuff. I mean how do you know that this " aggregation-initialization"? What are your sources, if I may ask? – LandonZeKepitelOfGreytBritn Mar 07 '17 at 01:27
  • @trilolil Stroustrup is pretty comprehensive, and answering questions on this site helps you retain and hone such knowledge. – Bathsheba Mar 07 '17 at 17:50
38

Yes, according to the rule of aggregate initialization, it's guaranteed (that all elements of array C will be value-initialized, i.e. zero-initialized to 0 in this case).

(emphasis mine)

If the number of initializer clauses is less than the number of members and bases (since C++17) or initializer list is completely empty, the remaining members and bases (since C++17) are initialized by their default initializers, if provided in the class definition, and otherwise (since C++14) by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates).


PS:

int A[5]; // Entries remain uninitialized

"remain uninitialized" might not be accurate. For int A[5];, all elements of A will be default-initialized. If A is static or thread-local object, the elements will be zero-initialized to 0, otherwise nothing is done, they'll be indeterminate values.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • Since you're quoting some formal specification (you should say which one, actually), `A[5]`, properly, is _default-initialized_. – edmz Aug 11 '16 at 10:23
14

In fact when you sayint A[5] = { 0 }; you are saying: Initialize the first element to zero. All the other positions are initialized to zero because of the aggregate inizialization.

This line is the real responsible for having your array full of zeroes: int A[5] = { };

That is why if you use int A[5] = { 1 }; you will only have the first position inizialized to 1.

rain_
  • 734
  • 1
  • 13
  • 24
0

At first, let's prove why every element in the below array A should be zero

int A[5] = {0};

How to guaranteed? It involves the below standards:

  1. It is a Aggregate initialization since it is array type, and its number of initializer clauses is less than the number of members, and the first element is copy-initialized as 0.

Each direct public base, (since C++17) array element, or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.

  1. The remaining elements in the array will follow the rule of Aggregate initialization rule, and do value-initialization

If the number of initializer clauses is less than the number of members and bases (since C++17) or initializer list is completely empty, the remaining members and bases (since C++17) are initialized by their default member initializers, if provided in the class definition, and otherwise (since C++14) copy-initialized from empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed.

  1. According to Value Initialization, the left 4 elements will routine into 'zero initialization' process

otherwise, the object is zero-initialized.

  1. According to Zero Initialization, the type of remaining elements is int which is a scaler type, so the left 4 elements will be initialized as 0

If T is a scalar type, the object's initial value is the integral constant zero explicitly converted to T.

  1. So every element in A should be zero

Proof done!

Finally, let's prove why every element in the below array B should be zero

int B[5] = {};

It is a value-initialization form, according to Value Initialization

In all cases, if the empty pair of braces {} is used and T is an aggregate type, aggregate-initialization is performed instead of value-initialization.

It will go into upper aggregate-initialization #2, and then every element in B array should be zero.

Proof done!

ravin.wang
  • 1,122
  • 1
  • 9
  • 26
  • The correct answer was accepted five years ago. –  Sep 20 '21 at 07:22
  • The original answer can't be proven with the strict proof, so it can't say it is guaranteed for all C/C++ compiler – ravin.wang Sep 20 '21 at 07:32
  • "can't be proven with the strict proof": what does that mean ? –  Sep 20 '21 at 07:46
  • Ok, delete the answer? I didn't find any cite from C/C++ specification to prove the related statement, and then it can't be guaranteed, right? Maybe you are a C/C++ professor, but for the some guys, I think it may need more information and cite from C/C++ specification to show what happened from the compiler level. – ravin.wang Sep 20 '21 at 08:50
  • Don't make such a fuss of it. The question was essentially about "is it UB or not ?" –  Sep 20 '21 at 10:49