web-dev-qa-db-fra.com

Initialisation partielle d'une structure C

Ce 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 j'ai écrit le 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("%d\n", myStruct.sj);
}

Je ne comprends pas pourquoi 4096 (Qui, selon moi, est une valeur "poubelle") est imprimé lorsque je commente line no. 7 Et j'obtiens 0 Lorsque je décommente line no. 7. Je ne pense pas que la déclaration arr ait quelque chose à voir avec l'enregistrement d'activation de main() (ou plutôt myStruct) qui devrait ressembler (à condition que nous ayons line no. 7 non commenté):

---------------
|  Saved PC   |
---------------
|  arr[2]     |
---------------
|  arr[1]     |
---------------
|  arr[0]     |
---------------
|  si         |
---------------
|  sj         |
---------------

Quelqu'un peut-il expliquer ce qui me manque ici?

27
babon

Lorsque vous faites cela:

struct s myStruct;
myStruct.si = 9;

Vous n'êtes pas initialisationmyStruct. Vous le déclarez sans initialiseur, puis exécutez une instruction pour définir un champ.

Comme 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 non liés peuvent modifier ce comportement. Dans votre exemple, l'ajout d'une variable supplémentaire c'est arrivé pour provoquer myStruct.sj à 0, mais rien ne garantit que ce sera le cas.

Pour initialiser une variable, vous devez lui donner une valeur au moment où elle est définie:

struct s myStuct = { 9 };

Si vous faites cela, vous verrez le contenu de myStruct.sj mis à 0. Ceci est garanti selon la section 6.7.8 de la norme C (avec un surlignage spécifique à ce cas):

10 Si un objet qui a une durée de stockage automatique n'est pas initialisé explicitement, sa valeur est indéterminée. Si un objet qui a une durée de stockage statique n'est pas initialisé explicitement , alors:

- s'il a un type de pointeur, il est initialisé à un pointeur nul;

- s'il a un type arithmétique, il est initialisé à zéro (positif ou non signé);

- s'il s'agit d'un agrégat, chaque membre est initialisé (récursivement) selon ces règles;

- s'il s'agit d'une union, le premier membre nommé est initialisé (récursivement) conformément à ces règles.

...

21 S'il y a moins d'initialiseurs dans une liste entre accolades qu'il n'y a d'éléments ou de membres d'un agrégat , ou moins de caractères dans un littéral de chaîne utilisé pour initialiser un tableau de taille connue qu'il n'y a d'éléments dans le tableau, le reste de l'agrégat doit être initialisé implicitement de la même manière que les objets qui ont une durée de stockage statique.

51
dbush

Dans ton cas,

 myStruct.si = 9;

est une instruction affectation, pas initialisation. Dans ce cas, la variable de structure (et les variables correspondantes) ne sont pas initialisées. Ainsi, vous finissez par lire la valeur d'une variable non initialisée sj, ce qui conduit à comportement non défini .

Tu peux essayer

struct s myStruct = {9};

pour voir le initialisation implicite en action.

15
Sourav Ghosh

Ce n'est pas un initialiseur - votre structure n'est pas initialisée, alors vous n'affectez que si. sj reste non initialisé.

Le livre fait référence à ce type de code:

struct s myStruct = {9};

... où sj est garanti égal à 0.

11
Quentin

Il s'agit essentiellement d'un exemple - plus ou moins complet - des bonnes 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
2
sjsam