Initialiser une structure à 0

116

Si j'ai une structure comme celle-ci:

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

Quelle serait la manière la plus simple d'initialiser cette structure à 0? Cela suffirait-il?

myStruct _m1 = {0};

ou Aurais-je besoin d'initialiser explicitement chaque membre à 0?

myStruct _m2 = {0,0};
Daan Timmer
la source

Réponses:

142

Le premier est le plus simple ( implique moins de frappe ), et il est garanti de fonctionner, tous les membres seront définis sur 0[Ref 1] .
Le second est plus lisible.

Le choix dépend de la préférence de l'utilisateur ou de celle que votre norme de codage impose.

[Ref 1] Référence C99 Standard 6.7.8.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 une chaîne littérale utilisée 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.

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

Alok Save
la source
9
Aussi, j'utilise = {};Cependant, je ne suis pas sûr que cela soit valide.
William Entriken
15
Les accolades vides @FullDecent pour l'initialisation sont une extension GNU.
a3f
2
@ alias65536 La question est étiquetée C et non C ++.
a3f
3
J'ai eu une erreur: "accolades manquantes autour de l'initialiseur [-Werror = accolades manquantes]" probablement à cause d'un tableau de membres: /
DrumM
3
@Edenia. Je ne suis pas d'accord. Je sais déjà ce que cela foo = {0}veut dire. Si je voyais foo = ZERO_FULL, je devrais grep pour la définition de ZERO_FULL.
Andrew Bainbridge
32

Si les données sont une variable statique ou globale, elles sont remplies de zéro par défaut, alors déclarez-la simplement myStruct _m;

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

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

Les compilateurs actuels (par exemple les versions récentes de gcc) optimisent cela assez bien dans la pratique. Cela ne fonctionne que si toutes les valeurs nulles (y compris les pointeurs nulles et la virgule flottante zéro) sont représentées comme tous les bits zéro, ce qui est vrai sur toutes les plates-formes que je connais (mais le standard C autorise les implémentations où c'est faux; je ne connais pas une telle implémentation) .

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

Mon sentiment est que l'utilisation memsetpour les structures locales est la meilleure, et cela traduit mieux le fait qu'au moment de l'exécution, quelque chose doit être fait (alors que généralement, les données globales et statiques peuvent être comprises comme initialisées au moment de la compilation, sans aucun coût au moment de l'exécution) .

Basile Starynkevitch
la source
7
Il n'y a aucune garantie que définir tous les octets de la structure sur 0sera équivalent à l'initialisation de tous les membres de la structure avec 0bien. Sur de nombreuses plates-formes, ce sera vrai, mais pas partout.
Sander De Dycker
1
Pouvez-vous partager un exemple, Sander? Véritable curiosité. (De toute évidence, ce n'est pas universellement vrai ne signifie pas nécessairement qu'il y a une exception facile à expliquer, mais s'il y en a ...)
Steven Fisher
2
La norme C permet au pointeur nul (ou un nombre à virgule flottante zéro) d'être représenté en mémoire par autre chose que tous les bits zéro. Très peu d'implémentations étranges le font (je ne peux en nommer aucune).
Basile Starynkevitch
-1, vous pourriez trouver l'initialisation que l'OP demande laide, mais c'est exactement ce qui est prévu par le standard et qui peut être facilement optimisé par tous les compilateurs. Ensuite, le formulaire {}n'est pas valide C mais uniquement disponible en C ++.
Jens Gustedt
7
@Steven: Je ne peux penser qu'aux plateformes obscures et / ou anciennes. La FAQ C contient une liste de plates-formes qui avaient un NULLpointeur qui n'était pas tous 0bits: c-faq.com/null/machexamp.html . Et puis il y a la possibilité que la plate-forme n'utilise pas IEEE 754 pour représenter des valeurs en virgule flottante, mais utilise une autre représentation qui n'a pas une valeur de tous les 0bits 0.0- mais il est vrai que je ne connais pas une telle plate-forme.
Sander De Dycker
19

Voir §6.7.9 Initialisation:

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 une chaîne littérale utilisée pour initialiser un tableau de taille connue qu'il n'y a d'éléments dans le tableau, le reste de l'agrégat doivent être initialisés 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};
dirkgently
la source
Plus particulièrement, c'est déjà C89: open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf#page=139 (Important pour des cibles de traitement de signal spécifiques)
Tobias