Question

Je pense qu'il devrait être 01 mais quelqu'un dit son « non défini », une raison à cela?

Était-ce utile?

La solution

c++ est à la fois une augmentation et une affectation. Lorsque l'affectation se produit (avant ou après un autre code sur cette ligne) est laissée à la discrétion du compilateur. Il peut se produire après la cout << ou avant.

se trouve dans la norme C99   http://www.open-std.org/JTC1 /SC22/wg14/www/docs/n1124.pdf

Vous pouvez le trouver à la page 28 dans le pdf ou la section 5.1.2.3

  

l'augmentation réelle de p peut se produire à tout moment entre le point de séquence précédent et le prochain point de séquence

Depuis que quelqu'un a demandé la norme C (psl c'est un C ++ question), il se trouve à la section 1.9.15 page 10 (ou 24 en format pdf)

  

évaluations des opérandes des opérateurs individuels et des sous-expressions d'expressions individuelles non séquencée

Il comprend également le bloc de code suivant:

i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined

Je sens que l'explication de la norme C99 est plus claire, mais il est vrai dans les deux langues.

Autres conseils

Il est un comportement non défini si vous modifiez une valeur, puis le lire (ou essayer de le modifier à nouveau) sans point de séquence intermédiaire. Le concept d'un point de séquence en C ++ est un peu technique (vous pouvez lire un peu ce ici ), mais l'essentiel est que l'insertion de flux (de <<) est pas un point de la séquence.

La raison pour laquelle ce comportement est indéfini est parce que, en l'absence d'un point de séquence, le compilateur est autorisé à réordonner les opérations de toute façon qu'il juge opportun. À savoir, il est permis de récupérer la valeur de c (et maintenez sur celui-ci pour la deuxième insertion) puis exécutez postfaces c++ pour obtenir la valeur pour la première insertion. Donc, vous ne pouvez pas être sûr que l'augmentation aura lieu avant ou après la valeur de c pour la deuxième insertion est déterminée.

La raison pour laquelle il est indéfini est que le compilateur est libre de calculer les paramètres de fonction dans un ordre quelconque. Considérez si vous appelez une fonction où (parce que vous êtes, mais il est plus facile d'imaginer quand il est dans la syntaxe de fonction):


  cout.output(c++).output(c);

Le compilateur peut frapper les paramètres dans l'ordre inverse, pour avancer, ou autre chose. Il peut appeler la première sortie avant de calculer le paramètre à la deuxième sortie ou il peut faire les deux et ensuite appeler.

Le comportement est défini, mais non précisée. L'ordre relatif de l'évaluation des deux utilisations de « c » dans l'expression est pas spécifié. Cependant, si vous le convertir en notation fonctionnelle, il ressemble à ceci:

cout.operator<<(c++).operator<<(c);

Il y a un point de séquence entre l'évaluation des arguments à une fonction, et exécuter le corps de la fonction, et les organes de fonction ne sont pas entrelacées, de sorte que le résultat est que le comportement non spécifié, et non défini.

Si vous n'avez pas un opérateur surchargé:

int c=0;
int a = c++ << c;

Ensuite, le comportement serait pas définie, à la fois parce que modificateur et en utilisant la valeur de c sans point d'séquence intermédiaire.

Edit: La litb séquence soulève est tout simplement faux. La norme spécifie (§ 1.9 / 17): « Lors de l'appel d'une fonction (si la fonction est ou non en ligne), il y a un point de séquence après l'évaluation de tous les arguments de la fonction (le cas échéant) qui a lieu avant l'exécution de toutes les expressions ou déclarations dans le corps de la fonction. "

Ce bien écrit avec l'idée que les arguments sont évalués, puis (immédiatement après) le corps de la fonction est exécutée. La séquence il suggère, dans lequel les arguments à une fonction sont évalués, puis à un autre des arguments, puis l'exécution des deux corps de fonction ne semble pas avoir été prévu, mais aussi n'est pas interdite. Cela, cependant, ne change rien - l'exigence est encore que: « ... il y a un point de séquence après l'évaluation de tous les arguments de la fonction (le cas échéant) ... »

La langue suivante sur l'exécution du corps ne supprime pas l'exigence d'un point de séquence après évaluation de tous les arguments de la fonction. Tous autre évaluation, que ce soit de l'organe de fonction ou d'autres arguments de la fonction résulte que le point de séquence. Je peux être aussi pédant et pervers que quiconque au sujet de mal à lire ce qui est clairement prévu (mais pas tout à fait a déclaré) - mais je ne peux pas imaginer à quel point « il y a un point de séquence après l'évaluation de toutes les fonctions arguments » peut être lu comme signifiant « il n'y a pas un point de séquence après l'évaluation de tous les arguments de la fonction. »

Du point de Neil est, bien sûr, correct: la syntaxe que je l'ai utilisé ci-dessus est pour les fonctions membres. Pour une surcharge non-membre, la syntaxe serait plus comme:

operator<<(operator<<(cout,c++), c);

Cela ne supprime pas l'obligation pour les points de séquence soit bien.

En ce qui étant non précisée: il est assez simple en fait: il y a un point de séquence après avoir évalué tous les arguments de la fonction, de sorte que tous les arguments pour un appel de fonction doit être pleinement évalué (y compris tous les effets secondaires), puis des arguments pour l'autre fonction appel peut être évalué (en tenant compte des effets secondaires de l'autre) - mais il n'y a pas d'exigence dont les arguments d'appel de la fonction doivent être évaluées en premier ou en second lieu, il pourrait être c, puis c++, ou il pourrait être c++, puis c -. mais il doit être l'un ou l'autre, pas un désentrelacement

Comme je le vois,     f (c ++); est équivalent à:     f (c); c + = 1;

    f (C ++, C ++); est équivalent à:     f (c, c); c + = 1; c + = 1;

Mais il peut être le cas que     f (C ++, C ++); devient     f (c, c + 1); c + 2 =;

Une expérience avec gcc et bruit, d'abord en C

#include <stdio.h>

void f(int a, int b) {
    printf("%d %d\n",a,b);
}

int main(int argc, char **argv) {
    int c = 0;
    f(c++,c++);

    return 0;
}

et en C ++

#include <iostream>

int main(int argc, char **argv) {
    int c = 0;
    std::cout << c++ << " " << c++ << std::endl;
    return 0;
}

est intéressant, comme gcc et g ++ compilé les résultats dans     dix tandis que clang compilé les résultats dans     0 1

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top