Comment initialiser une structure conformément aux normes du langage de programmation C

je veux initialiser un élément de structure, divisé en déclaration et initialisation. C'est ce que j'ai:

typedef struct MY_TYPE {
  boolean flag;
  short int value;
  double stuff;
} MY_TYPE;

void function(void) {
  MY_TYPE a;
  ...
  a = { true, 15, 0.123 }
}

est la façon de déclarer et d'initialiser une variable locale de MY_TYPE conformément aux normes de langage de programmation C (C89, C90, c99, C11, etc.)? Ou y a-t-il quelque chose de mieux ou du moins qui fonctionne?

Update j'ai fini par avoir un élément d'initialisation statique où je règle chaque subelement selon mes besoins.

368
demandé sur PF4Public 2008-12-01 16:13:17

13 réponses

dans (ANSI) C99, vous pouvez utiliser un initialiseur désigné pour initialiser une structure:

MY_TYPE a = { .flag = true, .value = 123, .stuff = 0.456 };

Edit: les autres membres sont initialisés comme zéro: "les membres de champ omis sont implicitement initialisés de la même façon que les objets qui ont une durée de stockage statique."( https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html )

613
répondu philant 2015-09-07 08:43:02

vous pouvez le faire avec un composé littéral . Selon cette page, il fonctionne en C99 (qui compte également comme ANSI C ).

MY_TYPE a;

a = (MY_TYPE) { .flag = true, .value = 123, .stuff = 0.456 };
...
a = (MY_TYPE) { .value = 234, .stuff = 1.234, .flag = false };

les désignations dans les initialisateurs sont optionnelles; vous pouvez aussi écrire:

a = (MY_TYPE) { true,  123, 0.456 };
...
a = (MY_TYPE) { false, 234, 1.234 };
166
répondu CesarB 2011-11-08 08:00:40

je vois que vous avez déjà reçu une réponse sur ANSI C 99, donc je vais jeter un os sur ANSI C 89. ANSI C 89 vous permet d'initialiser une structure de cette façon:

typedef struct Item {
    int a;
    float b;
    char* name;
} Item;

int main(void) {
    Item item = { 5, 2.2, "George" };
    return 0;
}

une chose importante à retenir, au moment où vous initialisez même un objet/ variable dans la structure, toutes ses autres variables seront initialisées à la valeur par défaut.

si vous n'initialisez pas les valeurs dans votre struct, toutes les variables contiendront des"valeurs d'ordures".

bonne chance!

82
répondu Ron Nuni 2014-05-05 11:10:24

a = (MYTYPE){ true, 15, 0.123 };

suffirait en C99

35
répondu qrdl 2008-12-01 13:27:22

tu l'as presque...

MY_TYPE a = { true,15,0.123 };

Rapide recherche sur les 'struct initialiser c' montre-moi ce

17
répondu Kieveli 2008-12-01 13:21:54

comme Ron Nuni a dit:

typedef struct Item {
    int a;
    float b;
    char* name;
} Item;

int main(void) {
    Item item = {5, 2.2, "George"};
    return 0;
}

une chose importante à retenir: au moment où vous initialisez même un objet/variable dans la structure, toutes ses autres variables seront initialisées à la valeur par défaut.

si vous n'initialisez pas les valeurs dans votre struct (i.e. si vous déclarez juste cette variable), toutes les variable.members contiendront des" valeurs d'ordures", seulement si la déclaration est locale!

si la déclaration est globale ou statique (comme dans ce cas), tous les non-initialisés variable.members seront initialisés automatiquement à:

  • 0 pour entiers et points flottants
  • '"151940920"' pour char (bien sûr, c'est la même chose que 0 , et char est un type entier)
  • NULL pour pointeurs.
12
répondu r_goyal 2015-05-26 05:56:09

C programming language standard ISO / IEC 9899: 1999 (communément appelé C99) permet d'utiliser un initialiseur désigné pour initialiser les membres d'une structure ou d'une union comme suit:

MY_TYPE a = { .stuff = 0.456, .flag = true, .value = 123 };

il est défini dans paragraph 7 , section 6.7.8 Initialization de la norme ISO/IEC 9899:1999 comme suit:

si un indicateur a la forme

. identificateur

ensuite, l'objet courant (défini ci-dessous) doit avoir une structure ou un type d'union et l'identificateur doit être le nom d'un membre de ce type.

noter que paragraph 9 de la même section stipule que:

sauf indication contraire expresse, aux fins de la présente sous-section, les membres non nommés d'objets de structure et de type d'union ne participent pas à l'initialisation. Les membres non nommés des objets de structure ont une valeur indéterminée même après l'initialisation.

dans la mise en œuvre GNU GCC cependant, les membres omis sont initialisés en tant que valeur de type zéro ou de type zéro. Comme indiqué dans la section 6.27 Initialisateurs désignés de la documentation GNU GCC:

les membres de champ omis sont implicitement initialisés de la même manière que les objets qui ont un stockage statique durée.

Microsoft Visual C++ compiler devrait prendre en charge les initialiseurs désignés depuis la version 2013 selon l'article de blog officiel C++ Conformance Roadmap . Le paragraphe Initializing unions and structs de initialiseurs article sur MSDN Visual Studio documentation suggère que les membres non nommés initialisés à des valeurs appropriées de type zéro comme GNU GCC.

Nouveau ISO / IEC 9899: 2011 La norme (communément appelée C11) qui a remplacé la norme ISO/IEC 9899:1999 conserve les initialisateurs désignés dans la section 6.7.9 Initialization . Il conserve également paragraph 9 inchangé.

11
répondu PF4Public 2016-06-08 11:43:11
void function(void) {
  MY_TYPE a;
  a.flag = true;
  a.value = 15;
  a.stuff = 0.123;
}
4
répondu robert 2014-05-19 13:37:10

si MS n'a pas mis à jour à C99, MY_TYPE a = { true, 15, 0.123};

2
répondu eddyq 2014-04-20 19:39:46

j'ai trouvé une autre façon d'initialiser les structures.

La structure:

typedef struct test {
    int num;
    char* str;
} test;

initialisation:

test tt = {
    num: 42,
    str: "nice"
};

selon la documentation de GCC, cette syntaxe est obsolète depuis GCC 2.5 .

2
répondu MichaelWang 2015-12-05 11:30:39

Je n'ai aimé aucune de ces réponses donc j'ai fait la mienne. Je ne sais pas si C'est ANSI C ou non, C'est juste GCC 4.2.1 dans son mode par défaut. Je ne me souviens jamais de la mise entre crochets, donc je commence avec un sous-ensemble de mes données et je me bats avec les messages d'erreur du compilateur jusqu'à ce qu'il se ferme. La lisibilité est ma première priorité.

    // in a header:
    typedef unsigned char uchar;

    struct fields {
      uchar num;
      uchar lbl[35];
    };

    // in an actual c file (I have 2 in this case)
    struct fields labels[] = {
      {0,"Package"},
      {1,"Version"},
      {2,"Apport"},
      {3,"Architecture"},
      {4,"Bugs"},
      {5,"Description-md5"},
      {6,"Essential"},
      {7,"Filename"},
      {8,"Ghc-Package"},
      {9,"Gstreamer-Version"},
      {10,"Homepage"},
      {11,"Installed-Size"},
      {12,"MD5sum"},
      {13,"Maintainer"},
      {14,"Modaliases"},
      {15,"Multi-Arch"},
      {16,"Npp-Description"},
      {17,"Npp-File"},
      {18,"Npp-Name"},
      {19,"Origin"}
    };

les données peuvent commencer la vie comme un fichier tab-délimité que vous recherchez-remplacer pour masser dans quelque chose d'autre. Oui, c'est Debian choses. Si une paire extérieure de {} (indiquant le tableau), puis une autre paire pour chaque structure à l'intérieur. Avec des virgules entre les deux. Mettre des choses dans un en-tête n'est pas strictement nécessaire, mais j'ai environ 50 articles dans ma structure donc je les veux dans un fichier séparé, à la fois pour garder le désordre hors de mon code et donc il est plus facile de remplacer.

1
répondu Alan Corey 2016-05-13 02:46:44

Structure en C peut être déclarée et initialisée comme ceci:

typedef struct book
{
    char title[10];
    char author[10];
    float price;
} book;

int main() {
    book b1={"DS", "Ajay", 250.0};

    printf("%s \t %s \t %f", b1.title, b1.author, b1.price);

    return 0;
}
0
répondu Ajay Parashar 2017-09-26 14:55:37

j'ai lu la Documentation de Microsoft Visual Studio 2015 pour initialiser les types D'agrégats pourtant, toutes les formes d'initialisation avec {...} sont expliquées ici, mais l'initialisation avec le point, nommé" designator " n'est pas mentionnée là. Il ne fonctionne pas aussi.

la norme C99 chapitre 6.7.8 initialisation explique la possibilité des désignateurs, mais à mon avis, il n'est pas vraiment clair pour les structures complexes. Le C99 la norme pdf .

dans mon esprit, il peut être mieux de

  1. utilisez le = {0}; - initialisation pour toutes les données statiques. C'est moins d'effort pour le code machine.
  2. utiliser des macros pour initialiser, par exemple

    typedef MyStruct_t{ int x, int a, int b; } MyStruct; define INIT_MyStruct(A,B) { 0, A, B}

la macro peut être adaptée, sa liste d'arguments peut être indépendante de la structure modifiée contenu. Il est approprié que moins d'éléments soient initialisés. Il est également approprié pour la structure imbriquée. 3. Une forme simple est: initialiser dans un sous-programme:

void init_MyStruct(MyStruct* thiz, int a, int b) {
  thiz->a = a; thiz->b = b; }

cette routine ressemble à ObjectOriented in C. Utilisez thiz , pas this pour la compiler avec C++ aussi!

MyStruct data = {0}; //all is zero!
init_MyStruct(&data, 3, 456);
0
répondu Hartmut Schorrig 2018-08-12 14:10:33