C y C++: inicialización parcial de la estructura automática.

Resuelto loop asked hace 12 años • 3 respuestas

Por ejemplo, si somestructtiene tres miembros enteros, siempre pensé que estaba bien hacer esto en la función C (o C++):

somestruct s = {123,};

El primer miembro se inicializaría en 123 y los dos últimos se inicializarían en 0. A menudo hago lo mismo con las matrices automáticas, escribiendo int arr[100] = {0,};de modo que todos los números enteros de una matriz se inicialicen en cero.


Recientemente leí en el Manual de referencia de GNU C que:

Si no inicializa una variable de estructura, el efecto depende de si tiene almacenamiento estático (consulte Especificadores de clase de almacenamiento) o no. Si es así, los miembros con tipos integrales se inicializan con 0 y los miembros de puntero se inicializan con NULL; de lo contrario, el valor de los miembros de la estructura es indeterminado.


¿Alguien puede decirme qué dicen los estándares C y C++ con respecto a la estructura automática parcial y la inicialización automática de matrices? Hago el código anterior en Visual Studio sin problemas, pero quiero ser compatible con gcc/g++, y tal vez también con otros compiladores. Gracias

loop avatar May 31 '12 13:05 loop
Aceptado

La documentación de gcc vinculada no habla de inicialización parcial , solo habla de inicialización (completa) o sin inicialización .

¿Qué es la inicialización parcial?

Los estándares no definen la inicialización parcial de objetos, ya sea que haya inicialización completa o sin inicialización. La inicialización parcial es una terminología no estándar que comúnmente se refiere a una situación en la que se proporcionan algunos inicializadores pero no todos, es decir: menos inicializadores que el tamaño de la matriz o la cantidad de elementos de la estructura que se inicializan.

Ejemplo:

int array[10] = {1,2};                    //Case 1:Partial Initialization

¿Qué es la inicialización (completa) o la ausencia de inicialización?

Inicialización significa proporcionar algún valor inicial a la variable que se está creando al mismo tiempo que se crea. es decir: en la misma declaración de código.

Ejemplo:

int array[10] = {0,1,2,3,4,5,6,7,8,9};    //Case 2:Complete Initialization
int array[10];                            //Case 3:No Initialization

El párrafo citado describe el comportamiento de Case 3.

Las reglas relativas a la inicialización parcial ( Case 1) están bien definidas por el estándar y estas reglas no dependen del tipo de almacenamiento de la variable que se inicializa.
AFAIK, todos los compiladores principales cumplen al 100% estas reglas.


¿Alguien puede decirme qué dicen los estándares C y C++ con respecto a la estructura automática parcial y la inicialización automática de matrices?

Los estándares C y C++ garantizan que incluso si una matriz de enteros está ubicada en el almacenamiento automático y hay menos inicializadores en una lista entre llaves, los elementos no inicializados deben inicializarse en 0.

Estándar C99 6.7.8.21

Si hay menos inicializadores en una lista entre llaves que elementos o miembros de un agregado, o menos caracteres en una cadena literal utilizada para inicializar una matriz de tamaño conocido que elementos en la matriz, el resto del agregado inicializarse implícitamente de la misma manera que los objetos que tienen una duración de almacenamiento estático.


En C++ las reglas se establecen con una pequeña diferencia.

C++03 Estándar 8.5.1 Agregados
Párrafo 7:

Si hay menos inicializadores en la lista que miembros en el agregado, entonces cada miembro no inicializado explícitamente deberá inicializarse con su valor (8.5). [Ejemplo:

 struct S { int a; char* b; int c; };
 S ss = { 1, "asdf" };

se inicializa ss.acon 1, ss.bcon "asdf"y ss.ccon el valor de una expresión de la forma int(), es decir, 0. ]

Si bien la inicialización del valor se define en
C++03 8.5 Inicializadores,
párrafo 5:

Inicializar el valor de un objeto de tipo T significa:
— si T es un tipo de clase (cláusula 9) con un constructor declarado por el usuario (12.1), entonces se llama al constructor predeterminado para T (y la inicialización está mal formada si T no tiene un constructor predeterminado accesible);
— si T es un tipo de clase no sindical sin un constructor declarado por el usuario, entonces cada miembro de datos no estáticos y componente de clase base de T está inicializado por valor;
— si T es un tipo de matriz, entonces cada elemento se inicializa con su valor;
— de lo contrario, el objeto se inicializa a cero

Alok Save avatar May 31 '2012 06:05 Alok Save

En C, los objetos nunca se inicializan parcialmente: si se inicializa alguna parte de ellos, se inicializa todo el objeto (y todos los subobjetos de forma recursiva). Si no se proporciona ningún inicializador explícito, los elementos se inicializan a "cero del tipo apropiado".

La cita en su pregunta se refiere a cuando el inicializador de todo el objeto se omite por completo, no cuando un subobjeto carece de un inicializador. Por ejemplo, suponiendo que arrtiene una duración de almacenamiento automático, entonces esto:

int arr[100] = { 123 };

inicializa arr[0]to 123y todos los demás elementos de arrto 0. Mientras que esto:

int arr[100];

deja todos los elementos de arrsin inicializar. Es a este último caso al que se refiere la cita.

caf avatar May 31 '2012 06:05 caf

Las versiones más recientes de gcc también permiten inicializar "parcialmente" y poner a cero al mismo tiempo:

typedef struct{
  int a,b,c;
}T;

T s = {0, .b=5};

los miembros de la estructura ahora tendrán estos valores:a=0, b=5, c=0

No tengo ninguna información sobre si otros compiladores permiten esto o no :p

rocket441 avatar Feb 26 '2013 19:02 rocket441