Frage

Ich denke, es sollte 01 sein, aber jemand sagt, es ist "undefiniert", irgendein Grund dafür?

War es hilfreich?

Lösung

c++ ist sowohl ein Inkrement als auch eine Zuordnung. Wenn die Zuordnung erfolgt (vor oder nach einem anderen Code in dieser Zeile), bleibt dem Ermessen des Compilers überlassen. Es kann nach dem auftreten cout << oder davor.

Dies kann im C99 -Standard gefunden werden http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf

Sie finden es auf Seite 28 im PDF oder Abschnitt 5.1.2.3

Das tatsächliche Inkrement von P kann jederzeit zwischen dem vorherigen Sequenzpunkt und dem nächsten Sequenzpunkt auftreten

Da jemand nach dem C ++ - Standard (da dies eine C ++ - Frage ist), kann er in Abschnitt 1.9.15 Seite 10 (oder 24 im PDF -Format) gefunden werden.

Bewertungen von Operanden einzelner Operatoren und der Subtimpressionen einzelner Ausdrücke werden nicht ausgerichtet

Es enthält auch den folgenden Codeblock:

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

Ich bin der Meinung, dass die Erklärung des C99 -Standards klarer ist, aber in beiden Sprachen wahr ist.

Andere Tipps

Es ist ein undefiniertes Verhalten, wenn Sie einen Wert ändern und ihn dann lesen (oder versuchen, ihn erneut zu ändern), ohne einen intervenierenden Sequenzpunkt. Das Konzept eines Sequenzpunkts in C ++ ist etwas technisch (Sie können ein wenig darüber lesen hier), aber das Endergebnis ist diese Streaminsertion (<<) ist nicht ein Sequenzpunkt.

Der Grund, warum dies ein undefiniertes Verhalten ist, ist, dass der Compiler ohne einen Sequenzpunkt die Operationen in irgendeiner Weise neu bestellen darf, wie er passt. Das heißt, es darf den Wert von abrufen c (und halten Sie es für das zweite Einfügen fest) und dann werden die Nachworte ausgeführt c++ Um den Wert für das erste Einfügen zu erhalten. Sie können also nicht sicher sein, ob das Inkrement vor oder nach dem Wert von auftritt c Für die zweite Einführung wird bestimmt.

Der Grund, warum es undefiniert ist, ist, dass der Compiler die Funktionsparameter in beliebiger Reihenfolge frei berechnen kann. Überlegen Sie, ob Sie eine Funktion aufrufen (weil Sie es sind, aber es ist einfacher, sich bei der Funktionssyntax vorzustellen):


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

Der Compiler kann die Parameter in umgekehrter Reihenfolge, Vorwärtsreihenfolge oder was auch immer treffen. Es kann die erste Ausgabe aufrufen, bevor der Parameter für die zweite Ausgabe berechnet wird, oder er kann beides und dann aufrufen.

Das Verhalten ist definiert, aber nicht spezifiziert. Die relative Reihenfolge der Bewertung der beiden Verwendungen von 'C' im Ausdruck ist nicht angegeben. Wenn Sie es jedoch in funktionale Notation umwandeln, sieht es so aus:

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

Es gibt einen Sequenzpunkt zwischen der Bewertung der Argumente an eine Funktion und der Ausführung des Körpers der Funktion und Funktionskörper sind nicht verschachtelt, sodass das Ergebnis nur nicht spezifiziert ist, nicht und definiertes Verhalten.

Wenn Sie keinen überlasteten Bediener hatten:

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

Dann wäre das Verhalten undefiniert, da sowohl das Modifizieren als auch die Verwendung des Wertes von verwendet werden c ohne intervenierende Sequenzpunkt.

Bearbeiten: Die Sequenz litb Auferbringt ist einfach falsch. Der Standard gibt (§1.9/17) an: "Beim Aufrufen einer Funktion (unabhängig davon Aussagen im Funktionskörper. "

Dies wurde eindeutig mit der Idee geschrieben, dass Argumente bewertet werden, und dann (unmittelbar danach) wird der Körper der Funktion ausgeführt. Die Sequenz, die er vorschlägt, in der Argumente an eine Funktion bewertet werden, dann scheint Argumente an eine andere, dann die Ausführung beider Funktionskörper nicht beabsichtigt zu sein, aber auch nicht verboten. Das ändert sich jedoch nichts - die Anforderung lautet immer noch: "... Es gibt einen Sequenzpunkt nach der Bewertung aller Funktionsargumente (falls vorhanden) ..."

Die nachfolgende Sprache über die Ausführung des Körpers entzieht die Anforderung für einen Sequenzpunkt nach der Bewertung aller Funktionsargumente nicht. Alle Eine andere Bewertung, unabhängig davon, ob der Funktionskörper oder andere Funktionsargumente für den Sequenzpunkt folgt. Ich kann so pedantisch und pervers sein wie jeder andere über das Fehllesen, was klar beabsichtigt ist (aber nicht ziemlich angegeben) - aber ich kann mir nicht vorstellen, wie "es einen Sequenzpunkt nach der Bewertung aller Funktionsargumente" gibt "als Bedeutung" Es gibt keinen Sequenzpunkt nach der Bewertung aller Funktionsargumente ".

Neils Punkt ist natürlich richtig: Die Syntax, die ich oben verwendet habe, ist für Mitgliedsfunktionen. Für eine Überlastung ohne Mitglied würde die Syntax eher ähnlich sein:

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

Dies wird jedoch auch nicht die Anforderung für Sequenzpunkte beseitigt.

Was nicht spezifiziert ist: Es ist wirklich ziemlich einfach: Es gibt einen Sequenzpunkt nach der Bewertung aller Funktionsargumente bewertet (unter Berücksichtigung von Nebenwirkungen des anderen) - aber es gibt keine Anforderung darüber, welche Argumente von Funktion Call zuerst oder zweiten bewertet werden müssen c, dann c++, oder es könnte sein c++, dann c - Aber es muss das eine oder andere sein, kein verschachtender.

Wie ich es sehe, f (c ++); ist äquivalent zu: f (c); C += 1;

Und f (c ++, c ++); ist äquivalent zu: f (c, c); C += 1; C += 1;

Aber es kann der Fall sein, dass F (C ++, C ++); wird f (c, c+1); C+= 2;

Ein Experiment mit GCC und Clang, zuerst in 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;
}

und in C ++

#include <iostream>

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

Ist interessant, da GCC und G ++ zusammengestellt wurden, was zu 1 0 zusammengestellt wurde, während Clang zusammengestellt wurde

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top