10
votes

Incrémentation des pointeurs, séquence exacte

Je viens de commencer à apprendre c, et je reçois que

*a++ = *b++


5 commentaires

Le compilateur est libre de faire tout ce qu'il aime tant que le programme se comporte correctement, il n'ya donc pas grand chose à dire sur la manière dont cela sera traduit en général. Tout ce que vous pouvez faire est de le compiler avec le compilateur que vous utilisez et examinez le code généré - cela vous dira simplement de votre compilateur particulier dans ce cas particulier.


Essayez d'observer et de comprendre un code ASM généré par GCC -S .


Dans * a ++ = * b ++; , ++ est postfix si d'abord * b attribué à * A * Code> B ++ et A ++ effectué.


Vous faites une erreur commune de débutant de confusion la précédente avec ordre des effets secondaires . Ils ont en fait très peu à faire les uns avec les autres. Lorsque vous dites a () + b () * c () in c, il n'y a aucune obligation que b () et c () c () être appelé avant a () juste parce que * est une priorité supérieure à celle + . Les fonctions peuvent être appelées dans n'importe quel ordre , tant que b () et c () sont appelés avant * , a () est appelé avant + et * est appelé avant + . Le compilateur peut choisir n'importe quel ordre des appels satisfaisant à ces contraintes.


@Grijeshchauhaan: Vous faites une erreur commune de débutant pour supposer que l'opération Postfix a un point défini sur lequel se produisent les incréments. Ce ne est pas. Un compilateur conforme est autorisé à effectuer les incréments à tout moment. Si vous ne comprenez pas pourquoi c'est, lisez ma réponse avec soin.


3 Réponses :


4
votes

1)

a = a+1;
b = b+1
*a = *b;


1 commentaires

Est-ce que c'est vrai que x = * a ++ est requis pour être équivalent à x = * A; a = A + 1; ? Un compilateur conforme pourrait-il la mettre en œuvre comme temp = a; A = A + 1; x = * TEMP; ?



3
votes

La séquence exacte dans laquelle les expressions sont évaluées et les effets secondaires appliqués sont laissés non spécifiés ; Tout ce qui est garanti est que le résultat de * b ++ (la valeur que B Pointe actuellement sur) est attribuée au résultat de * A ++ ( la valeur que a pointe actuellement) et que les deux pointeurs sont avancés. L'ordre exact des opérations variera.

Si vous voulez savoir comment votre plate-forme les gère, vous pouvez consulter le code machine généré, mais sachez qu'il peut toujours varier en fonction des paramètres du compilateur ou du code environnant.


0 commentaires

14
votes

Vous avez dit que vous croyez que:

var_a = a;
a = a + 1;
// must pointer check var_a here
var_b = b;
b = b + 1;
val = *var_b; // pointer checks var_b
*var_a = val;


5 commentaires

Donc l'expression a = * p ++; effectuée en 2 manières (1) premier p attribué dans certains var puis parce que ++ `a une priorité supérieure Donc, p mis à jour en points à l'emplacement suivant, puis dans deuxième étape valeur ancienne de p = var attribué à A comme a = * var . (2) premier * p Attribuer à A car ++ est l'opérateur postfix puis p Mises à jour du point suivant.


@Grijeshchaauhan: correct; Soit le commandement est légal dans C. En C #, la spécification nécessite d'abord les effets secondaires du côté gauche, le cas échéant, sont produits. Puis effet latéral de l'incrément de p , puis l'effet latéral de la déséroférance de l'ancienne valeur de p se produit (rappelez-vous, la déséroférance produit un effet secondaire en C # si le pointeur est invalide), puis l'effet secondaire de l'affectation se produit. C'est-à-dire que dans les effets secondaires de C # "I> laissés à droite pour les subexpressions et en ordre précédent pour les opérateurs.


Jamais connu avant de lire cette réponse que l'expression a = * p ++ peut être évaluée comme var = p; p = p + 1; A = * var !


@HACCKS: pareil pour toi. Je croyais aussi que malgré la nommée, cela ne signifie pas que le pré-augmentation de la pré-augmentation sera d'abord en mémoire, puis de retourner, et cela ne signifie pas que la post-incrétation reviendra d'abord puis écrivez en mémoire. Mais cette idée fausse a été supprimée maintenant.


@ERIFLIPPERT: VAR = A; est faux que je pense en génération de code dans le deuxième cas. Il devrait être var = * a; Corrigez-moi si je me trompe.