programming - Inicializar parcialmente una estructura C
typedef struct in c example (4)
Este link establece que "cuando una matriz o estructura automática tiene un inicializador parcial, el resto se inicializa a 0". Decidí probar lo que leí y escribí la siguiente pieza de código:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
//int arr[3] = {2}; // line no. 7
struct s {
int si;
int sj;
};
struct s myStruct;
myStruct.si = 9;
printf("%d/n", myStruct.sj);
}
No entiendo por qué 4096
(que creo que es un valor "basura") se imprime cuando comento la line no. 7
line no. 7
y obtengo 0
cuando descomente la line no. 7
line no. 7
. No creo que la declaración arr
tenga algo que ver con el registro de activación de main()
(o más bien myStruct
) que debería verse (siempre que tengamos la line no. 7
comentada):
---------------
| Saved PC |
---------------
| arr[2] |
---------------
| arr[1] |
---------------
| arr[0] |
---------------
| si |
---------------
| sj |
---------------
¿Alguien puede explicar lo que me falta aquí?
Cuando haces esto:
struct s myStruct;
myStruct.si = 9;
No estás inicializando myStruct
. Usted lo declara sin un inicializador , luego ejecuta una declaración para establecer un campo.
Debido a que la variable no está inicializada, su contenido no está definido y leerlo es un comportamiento indefinido . Esto significa que cambios aparentemente no relacionados pueden modificar este comportamiento. En su ejemplo, agregar una variable adicional causó que myStruct.sj
sea 0, pero no hay garantía de que sea el caso.
Para inicializar una variable, debe darle un valor en el momento en que se define :
struct s myStuct = { 9 };
Una vez que haga esto, verá que el contenido de myStruct.sj
establecido en 0. Esto está garantizado según la sección 6.7.8 del estándar C (con resaltado específico para este caso):
10 Si un objeto que tiene una duración de almacenamiento automática no se inicializa explícitamente, su valor es indeterminado. Si un objeto que tiene una duración de almacenamiento estática no se inicializa explícitamente , entonces:
-Si tiene tipo de puntero, se inicializa a un puntero nulo;
- si tiene tipo aritmético, se inicializa a cero (positivo o sin signo);
- si es un agregado, cada miembro se inicializa (recursivamente) de acuerdo con estas reglas;
-Si es una unión, el primer miembro nombrado se inicializa (recursivamente) de acuerdo con estas reglas.
...
21 Si hay menos inicializadores en una lista encerrada que elementos o miembros de un agregado , o menos caracteres en un literal de cadena usado para inicializar una matriz de tamaño conocido que no hay elementos en la matriz, el resto del agregado se inicializarán implícitamente de la misma manera que los objetos que tienen una duración de almacenamiento estática.
En tu caso,
myStruct.si = 9;
es una declaración de assignment , no de initialization . En este caso, la variable de estructura (y las variables correspondientes) no están inicializadas. Por lo tanto, terminas leyendo el valor de una variable sin inicializar sj
, que conduce a un comportamiento indefinido .
Puedes probar
struct s myStruct = {9};
para ver la inicialización implícita en acción.
Eso no es un inicializador: su estructura no está inicializada, entonces usted asigna solo si
. sj
permanece sin inicializar.
El libro se refiere a este tipo de código:
struct s myStruct = {9};
... donde sj
está garantizado que es 0.
Esto es básicamente un ejemplo más o menos completo de las excelentes respuestas que otros ya dieron.
#include<stdio.h>
struct{
int a;
int b;
}obj1={.a=0}; //Partial initialization
typedef struct struct_B{
int a;
int b;
}struct_B;
int main(void)
{
printf("obj1.b : %d/n",obj1.b);
struct_B obj2={.b=1,.a=0,0}; // b''s first value is overridden here as 0 immediately follows a
printf("obj2.b : %d/n",obj2.b);
struct_B obj3={0}; //Partial initialization, here the ''0'' value is meant for a as it comes first in the declaration
printf("obj3.b : %d/n",obj3.b);
struct_B obj4={.a=0}; //Partial initialization
printf("obj4.b : %d/n",obj4.b);
return 0;
}
Salida:
obj1.b : 0
obj2.b : 0
obj3.b : 0
obj4.b : 0