Initialisation partielle d'une structure C
lien indique que "Lorsqu'un tableau ou une structure automatique a un initialiseur partiel, le reste est initialisé à 0". J'ai décidé d'essayer ce que j'ai lu et écrit le morceau de code suivant:
#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("%dn", myStruct.sj);
}
je ne comprends pas pourquoi 4096
(qui est, je crois, une valeur "poubelle") est imprimé lorsque je commente line no. 7
et j'obtiens 0
quand je décommentez line no. 7
. Je ne pense pas que l' arr
déclaration a quelque chose à faire avec main()
's enregistrement d'activation (ou plutôt myStruct
) qui devrait ressembler (à condition que nous avons line no. 7
sans commentaire):
---------------
| Saved PC |
---------------
| arr[2] |
---------------
| arr[1] |
---------------
| arr[0] |
---------------
| si |
---------------
| sj |
---------------
quelqu'un peut-il expliquer ce que je manque ici?
4 réponses
Quand tu fais ceci:
struct s myStruct;
myStruct.si = 9;
Vous n'êtes pas initialisationmyStruct
. Vous déclarez sans initialiseur, puis d'exécuter une instruction pour définir un champ.
parce que la variable n'est pas initialisée, son contenu n'est pas défini, et sa lecture est comportement non défini. Cela signifie que des changements apparemment sans rapport peuvent modifier ce comportement. Dans votre exemple ajouter une variable supplémentaire passé cause myStruct.sj
à 0, mais il n'y a aucune garantie que ce sera le cas.
initialiser une variable, vous devez donner une valeur au moment de l' défini:
struct s myStuct = { 9 };
On vous le faites, alors vous verrez le contenu de myStruct.sj
mis à 0. Ceci est garanti selon la section 6.7.8 de la norme C (avec mise en avant spécifique à ce cas):
10 si un objet qui a une durée de stockage automatique est pas initialisé explicitement, sa valeur est indéterminée. Si un objet qui a la durée de stockage statique n'est pas initialisé explicitement puis:
- s'il a le type de pointeur, il est initialisé à un null pointeur:
- si elle est de type arithmétique, elle est initialisée à (positive ou non signé) zéro;
-si c'est un agrégat, chaque membre est initialisé (de manière récursive) selon ces règles;
- s'il s'agit d'un syndicat, le premier le membre nommé est initialisé (récursivement) selon ces règles.
...
21 S'il y a moins d'initialiseurs dans une liste d'accroches que là sont des éléments ou des membres d'un agrégat, ou moins de caractères dans un chaîne littérale utilisée pour initialiser un tableau de taille connue qu'il sont des éléments dans le tableau, le reste de la somme doit être initialisé implicitement le même que les objets qui ont statique durée de stockage.
dans votre cas,
myStruct.si = 9;
est un affectation déclaration initialisation. Dans ce cas, la variable de structure (et les variables correspondantes) n'est pas initialisée. Ainsi, vous finissez par lire la valeur d'une variable non initialisée sj
, ce qui mène à comportement non défini.
Vous pouvez essayer
struct s myStruct = {9};
voir la implicite initialisation en action.
ce n'est pas un initialiseur -- votre structure n'est pas initialisée, alors vous assignez seulement si
. sj
reste non initialisée.
le livre fait référence à ce genre de code:
struct s myStruct = {9};
... où sj
est garantie 0.
il s'agit essentiellement d'un exemple plus ou moins complet pour les grandes réponses que d'autres ont déjà données.
#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;
}
Sortie:
obj1.b : 0
obj2.b : 0
obj3.b : 0
obj4.b : 0