100 votes

Initialiser/remettre la structure à zéro/nulle

struct x {
    char a[10];
    char b[20];
    int i;
    char *c;
    char *d[10];
};

Je remplis cette structure et utilise ensuite les valeurs. À la prochaine itération, je veux réinitialiser tous les champs à la valeur 0 o null avant de commencer à le réutiliser.

Comment puis-je le faire ? Puis-je utiliser memset ou je dois passer par tous les membres et le faire individuellement ?

115voto

David Heffernan Points 292687

Définissez une instance statique de la structure avec les valeurs initiales, puis affectez simplement cette valeur à votre variable lorsque vous souhaitez la réinitialiser.

Par exemple :

static const struct x EmptyStruct;

Ici, je m'appuie sur Initialisation statique pour définir mes valeurs initiales, mais vous pouvez utiliser un initialisateur de structure si vous souhaitez des valeurs initiales différentes.

Ensuite, à chaque fois que vous faites le tour de la boucle, vous pouvez écrire :

myStructVariable = EmptyStruct;

1 votes

@David Heffernan : est-ce mieux que d'utiliser memset si je veux seulement tout remettre à zéro 0 ? ?

10 votes

@hari Je préfère moi-même cette approche. En utilisant memset me fait sentir sale. Je préfère laisser le compilateur se préoccuper de la disposition de la mémoire dans la mesure du possible. Strictement parlant, une telle utilisation de memset n'est pas portable, mais en pratique, je serais étonné que vous ayez jamais compilé votre code dans un endroit important. Donc, vous pouvez probablement utiliser memset en toute sécurité si vous le préférez.

2 votes

@hari, c'est conceptuellement mieux, car vous fournissez des valeurs d'initialisation par défaut (quelque chose comme un modèle de fabrique d'objets).

92voto

Jens Gustedt Points 40410

La façon de faire une telle chose lorsque vous avez le C moderne (C99) est d'utiliser une fonction littéral composé .

a = (const struct x){ 0 };

C'est un peu similaire à la solution de David, sauf que vous n'avez pas à vous soucier de déclarer une structure vide ou de savoir s'il faut la déclarer. static . Si vous utilisez le const comme je l'ai fait, le compilateur est libre d'allouer le littéral composé de manière statique dans un stockage en lecture seule si nécessaire.

0 votes

Est-ce que cela crée une instance de x sur la pile pour ensuite la copier dans a ? Pour les grandes structures/petites piles, cela pourrait être un problème.

1 votes

Comme toutes les optimisations, ceci est complètement dépendant du compilateur, donc vous devez vérifier ce que votre compilateur produit. "Habituellement" sur les compilateurs modernes, ce n'est pas le cas, ceux-ci peuvent très bien tracer les initialisations et ne font que ce qui est nécessaire, pas plus. (Et ne pensez pas que ces choses sont des problèmes avant de mesurer un réel ralentissement. Ils ne le sont généralement pas).

0 votes

Par problème je voulais dire stack overflow, merci pour votre réponse !

61voto

user411313 Points 1920

Mieux que tout ce qui précède est d'utiliser la spécification C standard pour l'initialisation des structures :

struct StructType structVar = {0};

Ici, tous les bits sont à zéro (jamais).

14 votes

Je ne pense pas que vous puissiez le faire à chaque fois autour d'une boucle.

2 votes

C'est en effet censé fonctionner. Mais malheureusement, gcc et g++ s'en plaignent. gcc génère des avertissements, tandis que g++ génère une erreur. Je sais que gcc et g++ sont en faute à ce sujet (ils sont supposés suivre les spécifications du Standard C), mais néanmoins, pour une bonne portabilité, il est obligatoire de prendre en compte de telles limitations.

3 votes

@Cyan Vous pouvez utiliser {} en C++. Les développeurs de gcc semblent Je ne suis pas sûr que le C++ soit censé supporter {0} et je ne suis pas familier avec cette partie de la norme moi-même.

36voto

templatetypedef Points 129554

En C, il est courant de mettre à zéro la mémoire d'un fichier de type struct en utilisant memset :

struct x myStruct;
memset(&myStruct, 0, sizeof(myStruct));

Techniquement parlant, je ne pense pas que cela soit portable car cela suppose que le NULL sur une machine est représenté par la valeur entière 0, mais il est largement utilisé car c'est le cas sur la plupart des machines.

Si vous passez du C au C++, veillez à ne pas utiliser cette technique sur tous les objets. Le C++ ne la rend légale que pour les objets sans fonctions membres et sans héritage.

2 votes

La norme C stipule que NULL est toujours 0. Si la machine est conçue de telle sorte qu'une adresse invalide prédéterminée n'est pas littéralement 0, le compilateur pour cette architecture doit s'adapter pendant la compilation.

10 votes

@KevinM Oui, le symbole "0" correspond toujours au pointeur NULL même s'il est entièrement nul ; mais le compilateur ne peut rien faire si vous mettez les bits à zéro en utilisant memset.

0 votes

"Le C++ ne rend cela légal que sur les objets sans fonctions membres et sans héritage." Il s'agit de savoir si le type est considéré comme une "vieille donnée ordinaire". Les critères dépendent de la version du langage C++.

23voto

Rudy Velthuis Points 11477

Si vous avez un compilateur compatible avec C99, vous pouvez utiliser

mystruct = (struct x){0};

Sinon, vous devriez faire ce que David Heffernan a écrit, c'est-à-dire déclarer :

struct x empty = {0};

Et dans la boucle :

mystruct = empty;

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