60 votes

Compilateurs et ordre d'argumentation de l'évaluation en C ++

Bon, je suis conscient que la norme dicte qu'une implémentation C++ peut choisir l'ordre dans lequel les arguments d'une fonction sont évalués, mais existe-il des implémentations qui fait "profiter" de cette dans un scénario où il serait réellement une incidence sur le programme?

Exemple Classique:

int i = 0;
foo(i++, i++);

Note: je ne suis pas à la recherche de quelqu'un pour me dire que l'ordre d'évaluation ne peut pas être invoqué, j'en suis bien conscient. Je suis seulement intéressé à savoir si les compilateurs réellement faire évaluer de gauche à droite parce que j'imagine que si ils ont fait beaucoup de mal écrits code de casser (à juste titre, mais ils seraient probablement encore se plaindre).

54voto

dirkgently Points 56879

Il dépend du type d'argument, la fonction appelée la convention d'appel, l'archtecture et le compilateur. Sur un système x86, le Pascal convention d'appel évalue les arguments de la gauche vers la droite alors que dans la convention d'appel C (__cdecl) il est de droite à gauche. La plupart des programmes qui s'exécutent sur plusieurs plates-formes prennent en compte les conventions d'appel de sauter surprises.

Il y a un bel article sur Raymond Chen blog si vous êtes intéressé. Vous pouvez également prendre un coup d'oeil à la Pile et de l'Appel de la section du manuel de GCC.

Edit: tant que nous coupent les cheveux en quatre: Ma réponse traite ce pas aussi une question de la langue mais comme une plate-forme de l'un. La langue standard n'a pas de garantie ou de préférer l'une sur l'autre et la laisse comme indéterminée. Note de la rédaction. Il ne dit pas ce n'est pas définie. Non précisé dans ce sens signifie quelque chose que vous ne pouvez pas compter, non portable comportement. Je n'ai pas le C spec/projet de pratique, mais il devrait être similaire à celle de mon n2798 projet C++ (C++)

Certains autres aspects et des opérations de la machine abstraite sont décrites dans la présente Norme Internationale n'est pas spécifié (par exemple, l'ordre d'évaluation des arguments à une fonction). Si possible, la présente Norme Internationale définit un ensemble admissible de comportements. Elles définissent le non déterministe aspects de la machine abstraite. Une instance de la machine abstraite peut donc avoir plus d'une séquence de l'exécution d'un programme donné et à une entrée donnée.

7voto

Krok Points 276

J'ai trouvé la réponse dans les normes c++ .

Paragraphe 5.2.2.8:

L'ordre d'évaluation des arguments n'est pas spécifié. Tous les effets secondaires de l'argument de l'expression des évaluations prendre effet avant que la fonction est entré. L'ordre d'évaluation de l'expression postfix et l'argument de l'expression de la liste est non spécifié.

En d'autres termes, Cela dépend du compilateur seulement.

6voto

jalf Points 142628

Lire ce

Ce n'est pas une copie exacte de votre question, mais ma réponse (et quelques autres) couvrir votre question ainsi.

Il existe de très bonnes raisons d'optimisation pourquoi le compilateur peut pas simplement choisir de droite à gauche, mais aussi intercaler entre eux.

Le standard n'a même pas la garantie d'une commande séquentielle. Elle seule garantit que lorsque la fonction est appelée, tous les arguments ont été pleinement évalués.

Et oui, j'ai vu quelques versions de GCC faire exactement cela. Pour votre exemple, foo(0,0) serait appelé, et je serais 2 par la suite. (Je ne peux pas vous donner le numéro exact de la version du compilateur. C'était il y a longtemps - mais je ne serais pas surpris de voir le comportement de pop-up à nouveau. C'est un moyen efficace pour planifier les instructions)

6voto

Stephen Chung Points 9467

Tous les arguments sont évalués. L'ordre n'est pas défini (conformément à la norme). Mais toutes les implémentations de C/C++ (que je connais) évaluer les arguments d'une fonction à partir de la droite vers la gauche.

Je crois que le droit-à-gauche de l'évaluation de l'ordre a été très très vieux (depuis les premiers compilateurs C). Certainement la voie avant le C++ a été inventé, et la plupart des implémentations de C++ serait de garder le même ordre d'évaluation, car au début C++ implémentations simplement traduit en C.

Il y a une raison technique pour l'évaluation des arguments de fonction de droite à gauche. Dans la pile des architectures, des arguments sont généralement poussé sur la pile. En C/C++, vous pouvez appeler une fonction avec des arguments plus que spécifié -- les arguments supplémentaires sont simiply ignoré. Si des arguments sont évalués de gauche à droite, et poussé de gauche à droite, puis la pile fente à droite sous le pointeur de pile tiendra le dernier argument, et il n'existe aucun moyen de la fonction pour obtenir le décalage de tout argument particulier (parce que le nombre réel d'arguments poussé dépend de l'appelant).

Dans une de droite à gauche, poussez la commande, la pile fente à droite sous le pointeur de pile aura toujours le premier argument, et le prochain emplacement détient le deuxième argument etc. Argument décalages sera toujours déterministe de la fonction (qui peut être écrit et compilé ailleurs dans une bibliothèque, séparément, d'où il est appelé).

Maintenant, de droite à gauche, poussez la commande n'a pas de mandat de droite à gauche de l'évaluation de l'ordre, mais au début de compilateurs, de la mémoire est rare. En droit-à-gauche de l'évaluation de l'ordre, de la même pile peut être utilisée sur place (essentiellement, après une évaluation de l'argument -- ce qui peut être une expression ou d'une fonction d'appel! -- la valeur de retour est déjà à la bonne position sur la pile). De gauche à droite de l'évaluation, les valeurs de l'argument doit être stocké séparément et de les pousser en arrière de la pile dans l'ordre inverse.

2voto

j_random_hacker Points 28473

Je m'attends à ce que la plupart des compilateurs modernes tentent d'entrelacer les instructions qui calculent les arguments, car ils sont requis par le standard C ++ pour être indépendants et donc dépourvus d'interdépendance. Cela devrait aider à garder les unités d'exécution d'un processeur profondément en pipeline et à augmenter ainsi le débit. (Au moins, je m'attendrais à ce qu'un compilateur prétendant être un compilateur optimiseur le fasse lorsque des indicateurs d'optimisation sont donnés.)

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