c++ arrays initialization

c++ inicialización de matriz



arrays initialization (5)

Posible duplicado:
Cómo inicializar un array en C
¿Inicialización de matriz, está haciendo referencia a un elemento anterior bien?

Me pregunto si es seguro hacer tal inicialización en el estándar c / c ++:

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

Se compila y ejecuta con éxito con gcc 4.5 y clang 2.9, pero ¿será siempre cierto?

Imprimiendo esta tabla da 5 6 6 . Su inicialización en ámbito global.

En general, es interesante tanto en c como en c ++, pero quiero usarlo en c ++ :)


En la norma C99, parece que el orden de inicialización de los miembros está garantizado:

§6.7.8 / 17: Cada lista de inicializadores encerrada tiene un objeto actual asociado. Cuando no hay designaciones presentes, los subobjetos del objeto actual se inicializan en orden de acuerdo con el tipo del objeto actual: elementos de matriz en orden de subíndice creciente , miembros de estructura en orden de declaración y el primer miembro nombrado de una unión. En contraste, una designación hace que el siguiente inicializador comience la inicialización del subobjeto descrito por el designador. Luego, la inicialización continúa en orden, comenzando con el siguiente subobjeto después de lo descrito por el designador.

Pero como @Tomalak menciona en el comentario, eso no proporciona una garantía total para la operación, ya que el compilador primero evaluará todos los argumentos y luego aplicará los resultados en el orden anterior. Es decir, la cita anterior no impone un orden entre la inicialización de la tab[0] y la evaluación de la tab[0]+1 expresión tab[0]+1 que se usa para inicializar la tab[1] (solo impone un orden entre la inicialización de tab[0] y tab[1] )

A partir del estándar de C ++, ni en el estándar actual ni en el FDIS del próximo estándar de C ++ 0x parecen tener una cláusula específica que defina el orden en que se realiza la inicialización. La única mención del pedido proviene de

§8.5.1 / 2 Cuando se inicializa un agregado, el inicializador puede contener una cláusula inicializadora que consiste en una lista de cláusulas inicializadoras, separadas por comillas, para los miembros del agregado, escritas en subíndice creciente o orden de miembro.

Pero eso solo se relaciona con el orden por el cual se escriben las entradas en el inicializador, no cómo se evalúa realmente.


Entonces, ahora he hecho un par de pruebas con respecto a tu problema.

Todas las compilaciones se han realizado con el código de ejemplo anterior, utilizando el siguiente esquema:

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

Esto produjo los siguientes resultados:

para GCC = gcc , los estándares -std=c89; -std=iso9899:1990; -std=iso9899:199409; -std=gnu89 -std=c89; -std=iso9899:1990; -std=iso9899:199409; -std=gnu89 -std=c89; -std=iso9899:1990; -std=iso9899:199409; -std=gnu89 dio -std=c89; -std=iso9899:1990; -std=iso9899:199409; -std=gnu89 resultado una advertencia: el initializer element is not computable at load time y el comportamiento no definido en el tiempo de ejecución, lo que significa que el segundo y tercer valor de la matriz fueron basura aleatoria.

las normas -std=c99; std=iso9899:1999; -std=gnu99 -std=c99; std=iso9899:1999; -std=gnu99 -std=c99; std=iso9899:1999; -std=gnu99 no produjo esta advertencia, pero también mostró un comportamiento indefinido en tiempo de ejecución.

para GCC = g++ , los estándares -std=c++98; -std=gnu++98; -std=c++0x -std=c++98; -std=gnu++98; -std=c++0x -std=c++98; -std=gnu++98; -std=c++0x no produjo ninguna advertencia, y el código funcionó como esperabas, dando como resultado una matriz que contiene los valores {5, 6, 6} .

Sin embargo, como la mayoría de las personas aconsejaron, podría ser poco aconsejable usar esto, ya que su código podría comportarse de manera diferente en otros compiladores, o tal vez incluso en otras versiones del mismo compilador, lo que generalmente es algo malo :)

Espero que haya ayudado.


Sí, probablemente funcionará como esperas que sea.
No - (no lo pediste pero) No lo uses, no hace lógica y es una mala práctica.


C ++ 03 / C ++ 11 respuesta

No, no lo hará.

En el lado derecho de = , la tab existe 1 pero, si tiene una duración de almacenamiento automática, aún no se ha inicializado, por lo que su uso de la tab[0] y la tab[1] está utilizando una variable sin inicializar.

Si la tab está en el ámbito del espacio de nombres (y, por lo tanto, tiene una duración de almacenamiento estático y se ha inicializado en cero), entonces esto es "seguro", pero el uso de la tab[0] no le dará 5 .

Es difícil proporcionar referencias estándar para esto, aparte de decir que no hay nada en 8.5 "Initializers" que lo hace explícitamente posible, y las reglas en otros lugares completan el resto.

1 [n3290: 3.3.2/1]: El punto de declaración para un nombre es inmediatamente después de su declarador completo (Cláusula 8) y antes de su inicializador (si existe) [..]


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

Si estas variables se declaran en el ámbito del espacio de nombres, entonces están bien, ya que las variables del ámbito del espacio de nombres están inicializadas en cero (debido a la inicialización estática , lea this para más detalles).

Pero si se declaran en el alcance de la función, la segunda línea invoca un comportamiento indefinido, ya que las variables locales no se inicializan de forma estática , es decir, la tab[0] y la tab[1] no están inicializadas, lo que se usa para inicializar la matriz. La lectura de variables sin inicializar invoca un comportamiento indefinido.