9
votes

Printf et ++ opérateur

#include<stdio.h>
main()
{
    int a=10;
    printf("\n %d %d", a, a++); //11 10
    a=10;
    printf("\n %d %d", a++, a); //10 11
    a=10;
    printf("\n %d %d %d ", a, a++,++a); //12 11 12
}

c

2 commentaires

+1 pour une bonne question .. Je ne savais pas que cela a fonctionné de cette façon


Le calcul des arguments à printf ne fait pas partie de l'exécution de printf . Les arguments doivent tous être calculés avant printf commence à exécuter.


5 Réponses :


3
votes

Aucune des sorties ne peut vraiment être qualifiée comme inattendue. Tous les arguments à une fonction sont évalués avant l'entrée sur la fonction elle-même - mais l'ordre de leur évaluation par rapport à l'autre n'est pas spécifié, tous ces résultats sont autorisés. Officiellement, votre dernier un (qui a deux instances distinctes d'incrémentation A ) a un comportement non défini, il n'est donc pas nécessaire de ne rien faire de manière raisonnable.


7 commentaires

S'il y a un point de séquence entre évaluer chaque argument, pourquoi le dernier devrait-il être plus faux que les autres?


Le dernier est "plus faux" car il modifie A deux fois sans point de séquence intermédiaire. Le reste ne modifie que A une fois.


@Unclebens: Il n'y a pas de point de séquence entre évaluer chaque argument. Il y a un appel de séquence après l'évaluation des opérandes et avant que la fonction ne soit appelée, mais il n'y a pas de points de séquence (dans l'exmple) alors que les arguments sont évalués.


@Jerry: Je pense que même les appels avec un incrément unique appliqué à «A» sont également un comportement indéfini - pas seulement celui avec deux incréments appliqués.


@JoHathon: C'est ouvert à un argument. Le libellé exact de la norme (§6.5/2) est le suivant: "Entre le point de séquence précédent et suivant, un objet doit avoir sa valeur stockée modifiée au plus une fois par l'évaluation d'une expression. En outre, la valeur antérieure doit être en lecture seule à déterminer la valeur à stocker. " J'ai vu (et participé à) plusieurs arguments sur Comp.StD.C sur la question de savoir si cela fait (code comme) les autres UB ou non. Au final, personne ne semble tout à fait sûr, mais personne ne peut proposer un libellé qui le ferait clairement.


Eh bien, g ++ dit pour printf ("% d% d", a, ++ a); que l'opération sur un "peut être" non définie - non non spécifiée. (C'est en mode C ++, mais les langues diffèrent-elles vraiment ici ?!)


@Unclebens: ce message semble assez précis. Le dernier est clairement ub; Les autres pourraient être, selon l'interprétation.



1
votes

Les paramètres de fonction ne sont pas évalués dans un ordre défini dans C. Par conséquent, on ne peut donc pas raconter à l'avance si a ou a ++ sera évalué en premier lorsque vous appelez printf .

voir Commande d'évaluation des paramètres avant une fonction Appelant en C


0 commentaires

2
votes

Vous appelez un comportement non défini en faisant référence à la fois 'A' et 'A ++' dans la liste des arguments.

Il n'est pas défini à quel ordre les arguments sont évalués. Différents compilateurs peuvent choisir des commandes différentes. Un seul compilateur peut choisir des commandes différentes à des moments différents.

Ne le faites pas!


0 commentaires

8
votes

rien ne va "de droite à gauche" dans l'évaluation de l'argument de la fonction. Lorsque des arguments de la fonction sont évalués, l'ordre d'évaluation n'est pas spécifié et il n'y a pas de points de séquence entre évaluer des arguments distincts. Cela signifie qu'il n'y a absolument pas de commande temporelle dans ce processus. Les arguments peuvent être évalués dans n'importe quel ordre et le processus de leur évaluation peut être étroitement liée.

Cependant, votre code souffre de problèmes encore pires. Les trois déclarations qui appellent printf produisent un comportement non défini (UB), car ils tentent de modifier le même objet ( A ) sans point de séquence entre les modifications (la troisième appel), ou ils tentent de modifier un objet et de le lire pour un but indépendant (le premier et le deuxième appel). Donc, il est trop tôt pour mentionner l'ordre d'évaluation. Le comportement de votre code est indéfini.


0 commentaires

3
votes

++ un moyen d'incrémenter une première, puis retournez d'évaluer l'expression. (une modification et l'expression évalue en tant que + 1)

A ++ signifie évaluer un (SO, ERM, A), puis l'incrémenter. Ainsi, A est passé, mais la valeur d'A est alors (c'est-à-dire après) changée à un + 1.


1 commentaires

Bien que les autres personnes disent qu'il n'y ait pas d'ordre d'évaluation non définie, j'ai également essayé d'expliquer les opérateurs postfix et préfixe ...