2013-04-08 4 views
12

Ich weiß, dass das bekannt vorkommt, aber es ist mir ein Problem in einem Test von Microsoft, um Praktikanten anzuwerben. Es scheint mir, dass y=++y nicht standardkonform ist, aber ich denke, es wäre vielleicht besser, sicher zu sein (nicht sicher, ob ich besser bin als diejenigen, die diese Tests bei MS schreiben). Also ich frage deinen Rat. Glauben Sie, dass solche Ausdrücke standardkonform sind und nicht zu undefiniertem Verhalten führen?`y = ++ y`, entspricht dieser Standard? [das erscheint in einem Test von Microsoft]

#include <stdio.h> 
int main(){ 
    int a = 10; 
    int b = 10; 
    a = ++a; //What ??? 
    b = b++; //What ??? 
    printf("%d %d\n",a,b); 
    return 0; 
} 

gcc beschwert sich darüber, wenn sie mit -Wsequence-point kompilieren verwendet. (Es wird nicht explizit angegeben, ob es sich um eine C oder C++ spezifische Problem.)

Aber nur vier Antworten zur Verfügung gestellt:

a) 10 10 
b) 11 10 
c) 10 11 
d) 11 11 

Obwohl man nicht nur eine Antwort auswählen eingeschränkt (so vielleicht sollte ich wählen? alle vier?)

Nun, meiner Meinung nach gibt es zwischen Selbstinkrementierung und Zuweisung keinen Sequenzpunkt. Das verstößt also gegen die Spezifikation. Nicht wahr?

+0

Wollen Sie Ihre Antwort in Bezug auf C++ 03 oder C++ 11? Sie denken über dieses Zeug auf verschiedene Arten nach. –

+0

Sie sind richtig. Dies ist ein nicht definiertes Verhalten. – Art

+0

Ja, es ist UB, aber ich würde immer noch b) als Antwort wählen: P –

Antwort

9

Sie sind beide wohldefiniertes Verhalten nach C++ 11. C++ 11 nicht einmal haben Sequenzpunkte, so ist eine Sequenz-Point-bezogene Warnung offensichtlich veraltet. Der Zuweisungsoperator erlegt seinen Argumenten eine Sequenzierung auf.

Edit:

Während jeder kann sich einig, dass i = ++i jetzt wohldefinierte Verhalten ist, ist es eher nicht-trivial, die Definiertheit i = i++ zu entscheiden.Intuitiv, sollte ich es beschreiben, wie gut definiert, aber die Norm eindeutig fest, dass

i = i++ + 1; 

UB ist, und ich sehe nicht die + 1 macht keinen Unterschied hier.

Die kurze ist, wenn Sie diese Frage beantworten möchten, müssten Sie ein Experte für die entschieden nicht-trivial C++ 11 Sequenzregeln sein, die es scheint, dass ich nicht bin, aber es scheint, dass die Antwort ist "keiner der oben genannten UB".

+0

@DeadMG Könnten Sie eine zusätzliche Frage beantworten, da Sie die ursprüngliche beantwortet: sollte nicht das Ergebnis '11 12' in C++ 11 sein? – lapk

+0

Nein. Warum sollte es sein? Stellen Sie auch eine andere Frage. – Puppy

+0

@DeadMG Weil 'b = 11;' und 'b = b ++;' macht 'b' immer noch gleich' 11', und wir haben post-increment, was 'b' gleich' 12' in 'printf' macht. Entschuldigung, ich dachte nicht, dass es eine eigene Frage wert wäre und ich konnte nicht verstehen, warum es keine solche Auswahl in der ursprünglichen Liste gab ... Vielleicht verstehe ich etwas falsch, dachte nur, um es zu klären. – lapk

4

Per C++ 03-Standard,
Sowohl die folgenden Aussagen ergeben undefiniertes Verhalten:

a = ++a; 
b = b++; 

Wie Sie richtig festgestellt, g ++ Punkte unter Warnung aus:

Warnung: Vorgang an 'a' kann undefiniert sein [-Wennfolgepunkt]

Beachten Sie, dass im Fall von UB die Antwort alles andere als (a), (b), (c), (d) sein kann.
Idealerweise sollte in der Testfrage eine Option für "undefiniertes Verhalten" vorhanden sein. Aber oft würde die Person, die die Frage vorbereitet, einfach im XYZ-Compiler kompilieren und es einreichen.

Hier ist eine verwandte SO-Post, die Undefined Behavior and Sequence Points erklärt.

+0

+1, obwohl ich mich über die Qualität der Compiler-Implementierung beschweren würde, wenn sie Code ausgibt, der in diesem Fall dazu führt, dass Dämonen aus meiner Nase fliegen. Ja, das wäre normenkonform, aber es wäre trotzdem scheiße. –

+1

'a = ++ a;' ist nicht UB in C++ 11. Es ist UB in C++ 03. –

+2

Sie sind falsch, da C++ 11 dies ändert. – Puppy

-4

Ich denke, es ist D) seit ++ a bedeutet inkrement a und dann die Operation ausführen, so wird es sein wie a = 11 tun. b ++ bedeutet, dass die Operation ausgeführt wird und dann inkrementiert wird. Sie werden also b = 10 zuweisen, aber dann wird b inkrementiert und erhält den Wert b = 11.

Gut für die Puristen: Es bedeutet "nichts und dann nichts", aber das ist das Verhalten. Ich habe es getestet (mit Visual C++ und G ++) und meine Antwort ist richtig a = 11 und b = 11.

+0

Es bedeutet nicht "etwas * und dann * etwas". –

+0

Nun, ich brauche * empirisches Ergebnis * nicht. Fast alle gängigen Compiler, die heutzutage verwendet werden, zeigen dieses Verhalten. Aber ich möchte wissen, ob ** dies erforderlich ist ** oder nur eine Fallback-Methode, die entweder angenommen werden kann oder nicht. – phoeagon

+2

Es ist unmöglich, undefiniertes Verhalten zu "testen", weil es undefiniert ist und jede Implementierung alles tun kann, was sie will. (Das ist unabhängig von der ursprünglichen Frage btw) –

0

a = ++ a; b = b ++; Diese Vorgänge gelten als undefiniert. Jeder Compiler kann tun, was er will. Ausgabe variiert auf Compiler der Prüfer umrahmt die Frage.