Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ array initialization [duplicate]

Possible Duplicate:
array initialization, is referencing a previous element ok?

I wonder if its safe to do such initialization in c/c++ standard:

int a = 5;
int tab[] = { a , tab[0] + 1 , tab[1] };

It successfully compiles and executes with gcc 4.5 and clang 2.9, but will it always be true?


Printing this table gives 5 6 6. Its initialized in global scope.


Generally its interesting in both, c and c++, but i want to use it in c++:)

like image 381
qba Avatar asked Sep 11 '11 13:09

qba


People also ask

How do you initialize an array with the same value?

Initializer List: To initialize an array in C with the same value, the naive way is to provide an initializer list. We use this with small arrays. int num[5] = {1, 1, 1, 1, 1}; This will initialize the num array with value 1 at all index.

Can we initialize array two times?

No. The array is not being created twice. It is being created once and then it is being populated.

Does C initialize arrays to 0?

Initialize Arrays in C/C++ c. The array will be initialized to 0 if we provide the empty initializer list or just specify 0 in the initializer list.


4 Answers

C++03/C++11 answer


No, it won't.

On the right-hand side of the =, tab exists1 but — if it has automatic storage duration — it has not yet been initialised so your use of tab[0] and tab[1] is using an uninitialised variable.

If tab is at namespace scope (and thus has static storage duration and has been zero-initialized), then this is "safe" but your use of tab[0] there is not going to give you 5.

It's difficult to provide standard references for this, other than to say that there is nothing in 8.5 "Initializers" that explicitly makes this possible, and rules elsewhere fill in the rest.


1[n3290: 3.3.2/1]: The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any) [..]

like image 99
Lightness Races in Orbit Avatar answered Oct 14 '22 20:10

Lightness Races in Orbit


int a =5;
int tab[] = { a , tab[0] + 1 , tab[1] };

If these variables are declared at namespace scope, then they're okay, as at namespace scope variables are zero-initialized (because of static initialization - read this for detail).

But if they're declared at function scope, then second line invokes undefined behaviour, since the local variables are not statically initialized, that means, tab[0] and tab[1] are uninitialized, which you use to initialize the array. Reading uninitialized variables invokes undefined behavior.

like image 24
Nawaz Avatar answered Oct 14 '22 20:10

Nawaz


In the C99 standard, it seems that the order of initialization of the members is guaranteed:

§6.7.8/17: Each brace-enclosed initializer list has an associated current object. When no designations are present, subobjects of the current object are initialized in order according to the type of the current object: array elements in increasing subscript order, structure members in declaration order, and the first named member of a union. In contrast, a designation causes the following initializer to begin initialization of the subobject described by the designator. Initialization then continues forward in order, beginning with the next subobject after that described by the designator.

But as @Tomalak mentions in the comment, that does not provide a full guarantee for the operation, as the compiler would first evaluate all of the arguments and then apply the results in the previous order. That is, the previous quote does not impose an order between the initialization of tab[0] and the evaluation of the expression tab[0]+1 that is used to initialize tab[1] (it only imposes an ordering between the initialization of tab[0] and tab[1])

As of the C++ standard, neither in the current standard nor the FDIS of the upcoming C++0x standard seem to have an specific clause defining the order in which the initialization is performed. The only mention of ordering comes from

§8.5.1/2 When an aggregate is initialized the initializer can contain an initializer-clause consisting of a brace-enclosed, comma-separated list of initializer-clauses for the members of the aggregate, written in increasing subscript or member order.

But that only relates to the order by which the entries in the initializer are written, not how it is actually evaluated.

like image 30
David Rodríguez - dribeas Avatar answered Oct 14 '22 19:10

David Rodríguez - dribeas


so, now I've run a couple of tests regarding your problem.

All compilations have been performed with your example code above, using the following scheme:

$(GCC) -o a.out test.c -Wall -Wextra -pedantic -std=$(STD)

This yielded the following results:

for GCC = gcc, the standards -std=c89; -std=iso9899:1990; -std=iso9899:199409; -std=gnu89 resulted in a warning showing up: initializer element is not computable at load time and undefined behaviour at runtime, meaning that the second and third value of the array were random garbage.

the standards -std=c99; std=iso9899:1999; -std=gnu99 did not produce this warning, but also showed undefined behaviour at runtime.

for GCC = g++, the standards -std=c++98; -std=gnu++98; -std=c++0x produced no warning, and the code worked as you'd expected it to, resulting in an array containing the values {5, 6, 6}.

However, as most of the people advised, it might be unwise to use this, since your code might behave differently on other compilers, or maybe even other versions of the same compiler, which is generally a bad thing :)

hope that helped.

like image 37
Andreas Grapentin Avatar answered Oct 14 '22 19:10

Andreas Grapentin