178 votes

Initialisation d'une structure à 0

Si j'ai une structure comme celle-ci :

typedef struct
{
    unsigned char c1;
    unsigned char c2;
} myStruct;

Quel serait le moyen le plus simple d'initialiser cette structure à 0 ? Est-ce que ce qui suit suffirait ?

myStruct _m1 = {0};

ou Devrais-je explicitement initialiser chaque membre à 0 ?

myStruct _m2 = {0,0};

2 votes

Remarque : si la structure comporte des octets de remplissage (en raison de l'alignement), aucune de ces méthodes ne garantit qu'ils sont initialisés. Cela peut être important lorsque l'on écrit la structure sur une mémoire externe, un réseau ou que l'on compare avec la fonction memcmp . Dans ce cas, il convient d'utiliser memset .

194voto

Alok Save Points 115848

La première est la plus facile( implique moins de saisie ), et son fonctionnement est garanti, tous les membres seront réglés sur 0 [Ref 1] .
Le second est plus lisible.

Le choix dépend de la préférence de l'utilisateur ou de la norme de codage imposée.

[Ref 1] Référence C99 Standard 6.7.8.21 :

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

Bonne lecture :
C et C++ : Initialisation partielle de la structure automatique

14 votes

J'utilise également = {}; Cependant, je ne suis pas sûr que cela soit valable.

26 votes

@FullDecent Les accolades vides pour l'initialisation sont une extension GNU.

1 votes

Cela vaut-il également pour les pointeurs ? L'initialisation zéro est-elle la même que l'initialisation nulle dans le cas de char * (par exemple) ?

51voto

Basile Starynkevitch Points 67055

Si la donnée est une variable statique ou globale, elle est remplie de zéros par défaut, il suffit donc de la déclarer myStruct _m;

Si les données sont une variable locale ou une zone allouée au tas, effacez-les avec memset comme :

memset(&m, 0, sizeof(myStruct));

Les compilateurs actuels (par exemple les versions récentes de gcc ) l'optimisent très bien dans la pratique. Cela ne fonctionne que si toutes les valeurs nulles (y compris les pointeurs nuls et les zéros en virgule flottante) sont représentées par tous les bits nuls, ce qui est vrai sur toutes les plates-formes que je connais (mais la fonction C permet des implémentations où cela est faux ; je ne connais aucune implémentation de ce type).

Vous pourriez peut-être coder myStruct m = {}; ou myStruct m = {0}; (même si le premier membre de myStruct n'est pas un scalaire).

J'ai le sentiment que l'utilisation de memset pour les structures locales est la meilleure, et elle traduit mieux le fait que quelque chose doit être fait au moment de l'exécution (alors qu'habituellement, les données globales et statiques peuvent être considérées comme initialisées au moment de la compilation, sans aucun coût au moment de l'exécution).

12 votes

Il n'y a aucune garantie que le fait de mettre tous les octets de la structure à 0 équivaudra à initialiser tous les membres de la structure avec la valeur 0 mais C'est le cas sur de nombreuses plateformes, mais pas partout.

3 votes

Pouvez-vous nous donner un exemple, Sander ? Simple curiosité. (Il est évident que le fait que ce ne soit pas universellement vrai ne signifie pas nécessairement qu'il y ait une exception facile à expliquer, mais s'il y en a une...)

2 votes

En C permet au pointeur nul (ou à un nombre à virgule flottante nul) d'être représenté en mémoire par autre chose que tous les bits nuls. Très peu d'implémentations étranges le font (je ne peux en citer aucune).

24voto

dirkgently Points 56879

Voir §6.7.9 Initialisation :

21 S'il y a moins d'initialisateurs dans une liste entourée d'accolades que t 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 ou de membres d'un agrégat. que le nombre d'éléments du tableau, le reste de l'agrégat sera initialisé implicitement de la même manière que les objets qui ont une durée de stockage statique.

Donc, oui, les deux fonctionnent. Notez qu'en C99, une nouvelle méthode d'initialisation, appelée initialisation désignée, peut également être utilisée :

myStruct _m1 = {.c2 = 0, .c1 = 1};

1 votes

Il s'agit notamment de la norme C89 : open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf#page=139 (Important pour des objectifs spécifiques de traitement du signal)

0 votes

Mais notez que cela fonctionne intuitivement pour {0} mais que ce n'est pas aussi clair si vous faites par exemple {1}. Il est facile de penser qu'il mettra tout à 1, mais il ne mettra que le premier à 1 et initialisera implicitement le reste, de sorte que vous vous retrouverez probablement avec 1,0.

13voto

pgibbons Points 39

Je pensais également que cela fonctionnerait, mais c'est trompeur :

myStruct _m1 = {0};

Lorsque j'ai essayé ceci :

myStruct _m1 = {0xff};

Seul le premier octet a été mis à 0xff les autres ont été fixés à 0 . Je ne prendrais donc pas l'habitude de l'utiliser.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X