2016-11-22 5 views
-1

Je voudrais éviter d'utiliser memset() sur une structure comme celle-ci:Éviter memset pour une structure de type multi

typedef struct { 
    int size; 
    float param1; 
} StructA; 

typedef struct { 
    StructA a; 
    unsigned int state; 
    float param2; 
} Object; 

Puis-je faire quelque chose comme ça (pseudo code, je ne peux pas vérifier ce moment)?

Object obj; 
int *adr = (int*)&obj; 
for (int i; i < sizeof(obj); i++) { 
    *adr++ = 0; 
} 

Va-t-il remettre à zéro chaque membre de obj?

EDIT: pour répondre aux questions sur les commentaires. J'ai travaillé sur certains cas (avec des structures de type uni), où memset est deux fois plus lent que l'initialisation à la main. Donc, je vais envisager d'essayer d'initialiser la structure multi-type aussi.

Éviter memcpy() serait bien aussi (en évitant le <string.h> lib).

+2

'int * adr'->' char * adr'. En outre, la réponse est oui. –

+8

Pourquoi voudriez-vous éviter 'memset()'? Et si vous voulez vraiment, n'utilisez pas 'int' utilisez' unsigned char' à la place. Mais vous devriez utiliser 'memset()' à la place, vous devriez vraiment. –

+1

En fait, ce qu'il fait est le même que 'memset'. –

Répondre

5

Le universel zéro initialiseur tout initialise (récursive) à zéro du type approprié.

Object object = {0}; 
+1

Oui, et il y a plusieurs réponses à ce sujet dans SO: http://stackoverflow.com/questions/5434865/quickest-way-to-initialize-an-array-of-structures-to-all-0s, http://stackoverflow.com/questions/11152160/initializing-a-struct-to-0, http: // stackoverflow .com/questions/7064314/what-is-0-in-c etc. Mais cette solution permet * d'initialiser * une variable de structure lors de la création seulement, alors que 'memset()' ou une boucle dans la question permettent * de re-initialiser * une variable déjà existante. – CiaPan

+0

Je l'ai essayé il y a quelque temps, ça marche. Mais je me souviens que je recevais un avertissement "initialiseur manquant pour membre". – MayurK

+1

Le texte de l'avertissement pourrait être un peu plus utile, peut-être: "initialiseur manquant pour le membre, en utilisant 0 pour les membres non spécifiés, récursivement, comme les mandats standard." – pmg

0

n °

Je préférerais utiliser memset:

memset(&obj, 0, sizeof(obj)); 

Ou si vous voulez faire votre chemin:

char* adr = (char*)&obj; 
for(int i = 0; i < sizeof(obj); i++) 
{ 
    *adr++ = 0; 
} 
+0

la seconde méthode utilise un «i» non initialisé et rompt la règle stricte d'aliasing, si vous lisez le char '0' de la structure via les membres. – mch

+3

@mch: Je pense que 'char *' est un cas spécial où la règle d'alias strict ne s'applique pas. –

+1

@PaulR Si vous écrivez quelque chose via un 'int *', vous êtes autorisé à le lire avec un 'char *', mais pas dans l'autre sens. http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule dit "Vous pouvez utiliser' char * 'pour l'alias à la place du mot de votre système Les règles autorisent une exception pour' char * ' (y compris 'signed char' et' unsigned char') Il est toujours supposé que char * 'alias les autres types, mais cela ne fonctionnera pas dans l'autre sens: il n'y a pas de supposition que votre structure aliases un tampon de caractères. – mch

-3

Vous devez utiliser memset, à moins que ce soit très difficile à faire. Comme il n'existe pas dans votre environnement et vous ne pouvez pas ajouter d'équivalent. C'est rapide, vérifie tous les cas de bord droit et est essentiellement sans bug.


Cela est assez proche pour fonctionner réellement. Mais sizeof produit la taille en octets. Vous devriez passer l'int à char.

Étant donné que tous les éléments impliqués sont d'une taille multiple de quatre, vous pouvez faire quelque chose comme ça et obtenir le même résultat. Barre tout remplissage que le compilateur pourrait insérer entre les champs, par exemple. Il peut placer chaque champ sur une région de 8 octets/64 bits, l'accès est donc plus rapide.

+1

Êtes-vous * sure *' obj' peut être aliasé par un 'int *'? –

+1

si 'sizeof (obj)' n'est pas un multiple de 4 cela ne fonctionnera pas du tout. –

+0

@MichaelWalz yup, c'est pourquoi j'ai qualifié l'ensemble de la réponse par «puisque tous les éléments impliqués sont d'une taille multiple de quatre». Peu importe ce que l'OP essaie de faire, c'est une mauvaise pratique de toute façon, mais ils devraient au moins avoir plus de moyens de se tirer une balle dans le pied. –

1

Vous pouvez créer un objet "zéro", puis le copier vers d'autres objets du même type. Peut-être que c'est plus rapide que memset(), je n'ai pas testé l'efficacité.

const Object zeroobject = {0}; 

/* ... */ 
Object obj; 
memcpy(&obj, &zeroobject, sizeof obj); 
/* assignment may work too */ 
obj = zeroobject; 
+0

Merci, mais en fait le point était trop éviter 'string.h' lib. – Bebs

+2

'' est un en-tête. Les fonctions déclarées ici font partie de la bibliothèque standard C. La meilleure façon d'éviter la bibliothèque standard C est d'utiliser une implémentation autonome. – pmg

+1

@Bebs: comme le souligne pmg, 'memcpy' n'est pas nécessaire,' obj = zeroobject; 'copie l'objet par défaut sur' obj' aussi efficacement que possible, en profitant de l'alignement intrinsèque des instances 'Object'. 'memcpy' et' memset' peuvent avoir besoin de tests supplémentaires pour déterminer comment effectuer la copie ou l'initialisation et pour les petites structures comme celle-ci, le surcoût d'un appel de fonction peut être perceptible si 'memset' ou' memcpy' ne sont pas générés en ligne . Inspectez le code généré par le compilateur, lancez des tests de performances, jouez avec les options du compilateur ... mais n'oubliez pas que la micro-optimisation est à court terme uniquement. – chqrlie

1

memset initialise la structure de tous les bits zéro. Cela initialiserait les entiers et les flottants à 0 sur les architectures conformes IEEE mais le C Standard ne le garantit pas. Sur un système exotique, cela peut ne pas initialiser param1 ou param2 à 0.0.

Si l'initialisation code à la main est plus rapide, utilisez que, ou utiliser un initialiseur statique:

Object obj = { 0 }; 
+0

Merci, c'est une bonne idée, mais je ne veux pas le mettre à zéro à la création, seulement plus tard. – Bebs