Est memset(&mystruct, 0, sizeof mystruct) même que mystruct = { 0 };?
Je suis en train de lire à propos de la initialisée valeurs par défaut d'un tableau/struct et cette question:
est memset(&mystruct, 0, sizeof mystruct)
même que mystruct = { 0 };
?
si elle ne l'est pas, quelle est la différence?
- Faites-vous? Alors qui était le
sizeof
variante qui n'a pas besoin de parens? sizeof
dans C, est un opérateur non pas une fonction. Le()
est facultatif. Voirmemset(&f, 0, sizeof f);
il fonctionne très bien pour moi.- Les gens, les regarder jusqu'à ce que la définition de
sizeof
est. C'est un opérateur unaire qui s'opère soit sur une variable ou un expression cast. Comme vous le savez déjà, une expression cast est un type entre parenthèses. Doncsizeof
lui-même n'a pas "besoin" de la parenthèse, c'est l'expression cast qui en a besoin. - Droit, mon propos était de souligner que la parenthèse n'est pas une partie de
sizeof
mais sur l '"objet", il fonctionne sur. De même avecreturn
qui me gêne beaucoup quand les gens mettent systématiquement entre parenthèses, comme si c'était une fonction. - Ok, je vais acheter que - désolé pour la prise de ce sur une tangente.
- Non, vous avez eu raison de fait référence de la norme, mon commentaire était en effet un peu bâclée.
- Pourquoi le premier commentaire a été supprimé? les commentaires maintenant semble un peu pas de sens.
Vous devez vous connecter pour publier un commentaire.
Pas.
... dira le compilateur pour appeler une fonction que nous nous attendons à ce set lors de l'exécution les données dans mystruct à zéro.
... va dire le compilateur défini par lui-même les données à zéro, ce qui signifie qu'il sera:
Notez que peut-être, le compilateur peut optimiser le memset dans un moment de la compilation d'instruction (comme le remplacement de la première version avec la deuxième version), mais je ne voudrais pas compter sur qui que
memset
est une fonction de la bibliothèque d'exécution, pas de langue intrinsèque (je ne suis pas un compilateur/écrivain de langue d'avocat, bien que).À venir à partir de C++, de mon propre point de vue est que le plus que vous pouvez faire à la compilation, et plus le compilateur sait au moment de la compilation, avant l'exécution, même commence, le mieux: Il permet au compilateur pour éventuellement optimiser le code et/ou de générer des avertissements/erreurs.
Dans le cas actuel, à l'aide de la
mystruct = { 0 };
notation pour initialiser unstruct
est toujours plus sûr que d'utiliser le memset parce qu'il est très très facile d'écrire quelque chose de mal en C avec unmemset
sans le compilateur se plaindre.Les exemples suivants montrent qu'il est facile pour le code pour faire quelque chose de différent de ce qu'il semble faire:
typedef struct A { int v ; } A ; void setZero(void) { A a = {0} ; }
à la place. Une auto de la variable est une variable locale, il n'a rien à voir avec les pointeurs.= {0} ;
peut produire de meilleurs résultats que memsetting à zéro (regardant le démontage du ccag, le confirme, que memset implique un appel de fonction).= {0} ;
le code est sûr, et seulement peut-être le plus rapide. Mais si vous avez des problèmes de performances, comme d'habitude, le profil de puis optimiser les goulets d'étranglement.memset(..,..,0)
) de ne pas faire de tout depuis le paramètre de taille est égale à zéro?mystruct = { 0 } ;
est une erreur de syntaxe, depuis{ 0 }
n'est pas une expression.Il s'agit d'un pédant de réponse, mais étant donné que la représentation interne d'un pointeur null est pas garanti d'être
0
le comportement dememset
contre brace-initialisation serait différent (memset
permettrait de faire la mauvaise chose). Cela dit, je n'ai jamais entendu parler d'une mise en œuvre qui a pris cette liberté d'avoir un non de tous les 0 modèle binaire pour les nuls.mystruct
présent.={ 0 }
considérant qu'il est d'une logique (plutôt que binaire) de l'initialisation.memset
à jouer du violon avec un faible niveau de bit mémoire-modèles.Théoriquement il y a une différence. La initialiser n'est pas nécessaire d'initialiser le rembourrage si il y en a dans
mystruct
.Par exemple:
Peut contenir:
où xx, yy et zz sont indéfinis octets où sur la pile.
Le compilateur est autorisé à le faire.
Cela dit, dans tous les termes pratiques, je n'ai pas rencontré un compilateur qui n'a encore. Le plus sain d'esprit des implémentations sémantique gérer ce cas, comme le
memset
.struct {uint8_t b; uint32_t i;} s
et l'on dits.b++;
sur une machine où octet magasins sont plus lents que la parole, les magasins, la machine d'effectuer un mot de l'incrément si chaque fois qu'il litb
, elle masque la valeur avec0xFF
(donc la valeur du padding bits n'a jamais été exposés à l'exception lors de la superposition de la structure avecuint8[]
?)est une instruction. Il peut être exécuté à tout moment où
mystruct
est visible, pas seulement au point où elle est définie.est en fait une erreur de syntaxe;
{ 0 }
n'est pas une expression valide.(Je vais supposer que
mystruct
est un objet de typestruct foo
.)Ce que vous pensez probablement de l'est:
où
{ 0 }
est un initialiseur.Si votre compilateur prend en charge, vous pouvez aussi écrire à:
où
(struct foo){ 0 }
est un littéral composé. Composé littéraux ont été introduites dans C99; certains compilateurs C, en particulier de Microsoft n'est probablement pas le soutenir. (Notez que le(struct foo)
est pas un opérateur de cast; il ressemble à l'un, mais il n'est pas suivi par une expression ou mis entre parenthèses le nom de type. C'est un distinctes de construction syntaxique.)Si votre compilateur ne supporte pas les littéraux composés, vous pouvez le contourner par la déclaration d'une constante:
Donc, c'est comment ils diffèrent dans la syntaxe et où vous pouvez les utiliser. Il y a aussi des différences sémantiques.
La
memset
appel jeux de tous les octets qui composent la représentation demystruct
à tous les zéros. C'est un très faible niveau de fonctionnement.D'autre part, l'initialiseur:
définit la première scalaire sous-composant de
mystruct
à 0, et établit toutes les autres sous-composants comme si ils ont été initialisé comme des objets statiques -- c'est à dire, de 0. (Ce serait bien si il y avait un nettoyeur destruct foo mystruct = { };
syntaxe de faire la même chose, mais il n'y en a pas.)Le truc, c'est mettre quelque chose à
0
n'est pas nécessairement la même chose que le réglage de sa représentation à tous les bits à zéro. La valeur0
est converti du type approprié pour chaque sous-composante scalaire.Pour les entiers, la langue garantit que tous les bits à zéro est une représentation de
0
(mais pas nécessairement la seule représentation de la0
). Il est très probable que l'établissement d'un entier0
allons mettre tous les bits à zéro, mais il est concevable qu'il puisse le régler à une autre représentation de0
. Dans la pratique, cela ne se produirait avec un dessein pervers compilateur.Pour les pointeurs, plus implémentations représentent des pointeurs null comme tous les bits à zéro, mais la langue n'a pas de garantie que l', et il y a eu dans le monde réel de mises en utiliser une autre représentation. (Par exemple, en utilisant quelque chose comme tous les bits on peut faire de pointeur null déréférence plus facile à détecter au moment de l'exécution.) Et la représentation peuvent varier pour différents types de pointeur. Voir la section 5 de la comp.lang.c FAQ.
De même, pour les types à virgule flottante, la plupart des implémentations représentent
0.0
comme tous les bits à zéro, mais la norme du langage n'est pas garantie.Vous pouvez probablement vous en sortir avec l'écriture de code que suppose la
memset
appel d'ensemble de tous les sous-composants à zéro, mais ce code n'est pas strictement portable -- et La Loi de Murphy implique que l'hypothèse ne seront pas en le plus inopportun moment possible, peut-être lorsque vous port le code d'un nouveau système important.