An interesting question arose as a side effect of some other question here, about the possible differences between how C and C++ handle (the non-static-storage-duration):
int arr[7] = {0};
Someone was stating that, in C++, the other elements were not guaranteed to be zero but I'm not sure I agree.
Now C11 states, in 6.7.9 Initialization /19
:
The initialization shall occur in initializer list order, each initializer provided for a particular subobject overriding any previously listed initializer for the same subobject; all subobjects that are not initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.
This means that the other six elements of arr
will be initilised to zero (since static int x;
would initialise x
to zero).
I'm unsure if this is also the case for C++. In the C++20 standard, 9.3.1 Aggregates /3
states:
When an aggregate is initialized by an initializer list as specified in
9.3.4
, the elements of the initializer list are taken as initializers for the elements of the aggregate. The explicitly initialized elements of the aggregate are determined as follows:(3.1) — (irrelevant stuff to do with designated initialiser lists and classes - pax).
(3.2) — If the initializer list is an initializer-list, the explicitly initialized elements of the aggregate are the first
n
elements of the aggregate, wheren
is the number of elements in the initializer list.
Then /4
states how the explicit initialisations work, and /5
handles the non-explicit cases:
For a non-union aggregate, each element that is not an explicitly initialized element is initialized as follows:
(5.1) — If the element has a default member initializer (10.3), the element is initialized from that initializer.
(5.2) — Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list (9.3.4).
(5.3) — Otherwise, the program is ill-formed.
It appears to me that our particular case is covered by (5.2)
so we have to go to 9.3.4
to see what happens to an int
initialised with an empty list ({}
). This goes through a lot of cases but I believe the first one that matches is:
(3.11) — Otherwise, if the initializer list has no elements, the object is value-initialized.
And, from 9.3 Initializers /8
:
To value-initialize an object of type T means:
(8.1) — if T is a (possibly cv-qualified) class type (Clause 10) with either no default constructor (10.3.4) or a default constructor that is user-provided or deleted, then the object is default-initialized;
(8.2) — if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
(8.3) — if T is an array type, then each element is value-initialized;
(8.4) — otherwise, the object is zero-initialized.
Hence, it's 8.4
which seems to be the controlling clause, meaning C++ will also initialise the non-explicit elements of the array to zero.
Is my reasoning correct? Will C++, on encountering int arr[7] = {0};
, set all elements to zero?
int arr[7] = {0};
will explicitly initialize the first element to zero, then the compiler will add code to initialize the remaining elements to zero. – Some programmer dudeint arr[n]={value}
didn't guarantee that all elements would bevalue
. So, they're correct forvalue != 0
but, since I was using{0}
as the init list, I thought it strange. I just wanted clarification since ISO C++ is so much more headache-inducing than ISO C :-) – paxdiablo