2012-06-18 4 views
10

den folgenden Code in C vor:dies in C-Schleife Code helfen, ein Verständnis Brauchen

void main() 
{ 
    int a=0; 

    for(printf("\nA"); a; printf("\nB")); 

    printf("\nC"); 
    printf("\nD");  
} 

Wenn ich es mit Turb C++ Version 3.0 und gcc-4.3.4 kompilieren, ich folgendes als die Ausgabe erhalten in Sowohl die Fälle:

A 
C 
D 

Allerdings, wenn ich den folgenden Code kompilieren:

void main() 
{ 
    for(printf("\nA"); 0; printf("\nB")); 

    printf("\nC"); 
    printf("\nD"); 
} 

die Ausgabe von gcc-4.3.4 ist die gleiche wie in der Pre Fall aber Turbo C++ 3.0 produziert folgende Ausgabe:

A 
B 
C 
D 

Zunächst einmal habe ich keine Ahnung, was hier passiert! Plus, wie kommt es, dass die Ausgabe des gcc-Compilers für beide Codes gleich ist, aber im Fall des turboC++ 3.0-Compilers ist die Ausgabe anders? Kann jemand bitte etwas Licht abwerfen?

EDIT:

Eigentlich jemand diese Frage in einem Interview für ein IT-Unternehmen gefragt wurde, und als er die Antwort geben scheiterte, gab den Interviewer diese Erklärung. Aber ich finde das dumm. Wie können Sie jemanden bitten, einen "Fehler" zu verwenden, als ob es sich um eine "Einrichtung" handelt, die von der Sprache bereitgestellt wird? Um es als "Facility" und "Technik" zu bezeichnen, ob wir 0 als Literal im zweiten Ausdruck übergeben oder eine Variable, deren Wert 0 ist, sollte das Ergebnis dasselbe gewesen sein.

Habe ich falsch zu dem Schluss, dass der Interviewer sehr dumm war, eine Frage so zu stellen und dass es seine Inkompetenz zeigt?

+5

Dies ist ein interessanter Unterschied in Compilern, aber warum in der Welt würden Sie diese Art von 'for' Schleife in erster Linie verwenden? – JAB

+0

Es sieht für Sie aus, dass Sie die Syntax für die "for" -Schleife in C völlig falsch verstanden haben? Du kannst nicht einfach erraten, wie man Dinge in einer Programmiersprache schreibt, du brauchst ein Buch oder einen Webkurs oder so etwas! –

+3

@ ThomasPadron-McCarthy Eigentlich ist die Syntax in Ordnung. Es scheint keinen guten Nutzen zu haben, aber es ist vollkommen gültig, genauso wie der Satz "Meine Kälte ist ein Zeh" syntaktisch vollkommen gültig ist, aber ein Nonsense-Satz ist. Der erste Teil, printf ("\ nA") ', wird am Anfang der Schleife ausgeführt; Der Sentinel-Ausdruck, der bewirkt, dass die Schleife bei der Auswertung von false/0 nicht mehr ausgeführt wird, ist ein "a" für den ersten (was == 0) und ein Literal "0" für den zweiten; [Forts.] – JAB

Antwort

12

Der TCC-Ausgang für das 2. Beispiel ist falsch.

Vom C99 Standard:

Die Anweisung

für (Klausel-1;expression-2;Ausdruck-3)Aussage

verhält sich wie folgt: Der Ausdruck Ausdruck-2 ist der steuernde Ausdruck, der vor jeder Ausführung des Schleifenkörpers ausgewertet wird. Der Ausdruck Ausdruck-3 wird als void Ausdruck nach jeder Ausführung des Schleifenkörpers ausgewertet. [...]

Offensichtlich gibt es keine Wiederholungen hier, so Ausdruck-3 sollte niemals ausgeführt werden.

Auch in dem C90-Standard (oder zumindest in einem draft that I found), heißt es:

Außer für das Verhalten einer Anweisung in der Schleife weiter, die Anweisung

 for ( expression-1 ; expression-2 ; expression-3) statement 

und die Reihenfolge der Anweisungen

 expression-1 ; 
    while (expression-2) { 
       statement 
       expression-3 ; 
    } 

sind gleichwertig.

+0

Das hätte ich mir gedacht. Ich werde meine Antwort entfernen. – Jack

+0

Offensichtlich ist Turbo C++ 3.0 älter als 8 Jahre. Es könnte eine seltsame Optimierungstechnik sein. –

+0

@HristoIliev: Siehe meine aktualisierte Antwort ... –

3

Turbo C++ 3.0 wurde in den 1990er Jahren veröffentlicht und wurde sehr schnell mit einer Version 3.1 nachverfolgt.

Ich würde vermuten, dass Ihr uralter Compiler eine Reihe von Fehlern hatte, die schnell aktualisiert wurden. Darüber hinaus könnte es nicht solche Bugs gehabt haben, aber möglicherweise optimierte Baugruppe emittiert haben, die unter den neuen Rohrauskleidungsarchitekturen versagt.

In jedem Fall ist es garantiert die Turbo C++ 3.0 ist nicht auf Ihrer aktuellen Plattform unterstützt. Wenn es darum geht, dass ein Compiler nicht unterstützt wird, weil die Plattform fast 20 Jahre später erstellt wurde, kann man nichts falsch machen, wenn das falsche Programm ausgegeben wird.

+0

AFAIK, Änderungen an Dingen wie CPU-Pipelining sollte für den Programmierer transparent sein. –

1

Die Semantik von for ist, dass der erste Ausdruck ausgewertet (Initialisierer) dann der zweite Ausdruck ausgewertet wird (Terminator), dann, wenn der Terminator ausgewertet, um nicht null der Körper des For ausgeführt wird, dann der dritte Ausdruck (Advancement) wird ausgewertet und zurück auf die Auswertung des Terminators.

Da Sie keinen Körper haben, wird dieser Teil zu keinen ausgewerteten Ausdrücken. Auf dieser Grundlage sollte die Schleife wie folgt ausgeführt werden:

printf("\nA"); 
a; // yields 0 -> terminate loop 

Dies ist in der Tat, was passiert.

In Ihrem zweiten Beispiel sollte das gleiche passieren (wie gcc ist) als 0 bis 0 bewertet

Es ist möglich, dass Turbo C++ - Sehen Sie die 0 konstant - versucht, einige auszuführen Art einer Loop-Abrollungsoptimierung (und konnte es nicht richtig machen)

+0

Ich dachte fast, dass die Schleife entrollende Geschichte plausibel ist, bis ich realisierte, dass es nicht "i <0" war, sondern nur "0", was kein wahrscheinliches Ziel für Loop-Abroll-Optimierung ist. – lvella

2

Der gcc-Ausgang ist korrekt.

Die Turbo C++ 3.0-Ausgabe im ersten Fall ist korrekt.

Die TurboC++ 3.0-Ausgabe im zweiten Fall ist falsch.

Es scheint, dass Sie im Turbo C++ 3.0-Compiler einen Edge-Case gefunden haben, der zu einer falschen Codegenerierung führt.

A für-Anw in C oder C++ hat die allgemeine Syntax

für (Initialisierung; test; Reinitialisierung) stmt

Die Initialisierungen einmal durchgeführt, bevor die Schleife beginnt. Der Test wird am Anfang der Schleife durchgeführt. Wenn der Test wahr ist, wird der Stmt ausgeführt und dann die Reinitialisierung, und die Schleife wird wiederholt.

In Ihrem Fall ist printf ("\ nA") die Initialisierung, a (oder 0) ist der Test, printf ("\ nB") ist die Reinitialisierung, und der stmt ist leer.

Sie sollten das A (und Sie haben) gesehen haben. Der Test sollte im ersten Durchgang fehlgeschlagen sein, was bedeutet, dass Sie den STMT nie gesehen haben sollten (aber Sie nicht wissen), und Sie sollten das B nie gesehen haben. Das ist, wo Turbo C++ 3.0 beim zweiten Test vermasselte.

Verwandte Themen