2010-07-26 2 views
20

oder "Deklarieren von mehreren Variablen in einem for-Schleife ist verboten",In C++, warum kann ich nicht schreiben, eine für() Schleife wie folgt: for (int i = 1, Doppel i2 = 0;

?! Mein ursprünglicher Code

for(int i = 1, int i2 = 1; 
     i2 < mid; 
     i++, i2 = i * i) { 

war ich eine Schleife durch die ersten so viele Plätze wollte, und beide wollte die Zahl und ihr Quadrat, und die Stoppbedingung auf dem Platz abhing. Dieser Code scheint der sauberste Ausdruck zu sein Absicht, aber es ist ungültig.Ich kann mir ein Dutzend Möglichkeiten vorstellen, um dies zu umgehen, also bin ich nicht auf der Suche nach der besten Alternative, aber für ein tieferes Verständnis, warum das ungültig ist.Ein bisschen Sprachgesetzgebung, wenn Sie so wollen.

Ich bin alt genug, um zu merken, wenn Sie zu Beginn der Funktion aller Variablen zu erklären haben, so dass ich zu schätzen die

for(int i = 0; .... 

Syntax. Um es zu lesen sieht es so aus, als ob Sie nur eine Typdeklaration im ersten Abschnitt einer for() -Anweisung haben können. So können Sie tun

for(int i=0, j=0; ... 

oder sogar leicht barock

for(int i=0, *j=&i; ... 

aber nicht die zu Mein vernünftig

for(int i=0, double x=0.0; ... 

Weiß jemand, warum? Ist das eine Einschränkung von for()? Oder eine Beschränkung Komma-Listen, wie „das erste Element einer Kommaliste kann einen Typen deklarieren, aber nicht die andere? Ist die folgenden Verwendungen von Kommata getrennte syntaktischen Elemente von C++?

(A)

for(int i=0, j=0; ... 

(B)

int i = 0, j = 0; 

(C)

int z; 
z = 1, 3, 4; 

Alle da draußen Gurus?

============================================== ======

Aufgrund der guten Antworten, die ich bekommen habe, ich glaube, ich die Frage schärfen:

In einer for-Anweisung

for(X; Y; Z;) {..... } 

was sind X, Y und Z ?

Meine Frage war über C++, aber ich habe keine großartige C++ Referenz. In meiner C-Referenz (Harbison und Steele 4. Auflage, 1995), sie sind alle drei Ausdrücke, und mein gcc erfordert C99-Modus zu verwenden (int i = 0;

In Stroustrup, sec 6.3 wird die für Anweisung Syntax als

gegeben

für (für-init-Anweisung, Bedingung; expression) Aussagen

So hat C++ eine besondere syntaktische Anweisung an die erste Klausel gewidmet in für(), und wir können nehme an, dass sie spezielle Regeln haben, die über die für einen Ausdruck hinausgehen. Klingt das gut?

+0

mögliche Duplikate von [Mehrere Zähler Problem In For-Schleife] (http://StackOverflow.com/Questions/2340073/Multiple-Counter-Problem-in-For-Loop) –

+0

mögliche Duplikate von [Kann ich Variablen von verschiedenen deklarieren Typen bei der Initialisierung einer for-Schleife?] (http://stackoverflow.com/questions/8644707/cani-i-declare-variables-of-different-types-in-the-initialization-of-a-for-loop) –

Antwort

16

int i = 1, double i2 = 0; ist keine gültige Deklarationsanweisung, daher kann sie nicht innerhalb der for Anweisung verwendet werden. Wenn die Anweisung nicht außerhalb der for stehen kann, kann sie nicht innerhalb der for Anweisung verwendet werden.

Bearbeiten: In Bezug auf Ihre Fragen zu Komma-Operatoren, Optionen 'A' und 'B' sind identisch und sind beide gültig. Option 'C' ist ebenfalls gültig, wird aber wahrscheinlich nicht das tun, was Sie erwarten würden. z wird zugewiesen 1, und die Anweisungen 3 und 4 tun eigentlich nichts (Ihr Compiler wird wahrscheinlich Sie über "Aussagen ohne Wirkung" warnen und sie weg optimieren).

Update: Um die Fragen in Ihrer Adresse bearbeitet, hier ist, wie der C++ spec (§ 6.5) definiert for:

for (for-init-statement condition(opt) ; expression(opt)) statement 

Es definiert ferner for-init-statement entweder als expression-statement oder simple-declaration. Sowohl condition als auch expression sind optional.

Die for-init-statement kann alles sein, das eine gültige expression-statement (wie i = 0;) oder simple-declaration (wie int i = 0;). Die Aussage int i = 1, double i2 = 0; ist keine gültige simple-declaration gemäß der Spezifikation, so ist es nicht gültig mit for zu verwenden. Als Referenz wird ein simple-declaration definiert (in Abschnitt 7) als:

attribute-specifier(opt) decl-specifier-seq(opt) init-declarator-list(opt) ; 

wo decl-specifier-seq den Datentyp und Schlüsselwörter wie static wären oder extern und init-declarator-list würde eine durch Kommata getrennte Liste von Deklaratoren und deren optional Initialisierungen sein. Beim Versuch, mehr als einen Datentyp in denselben simple-declaration zu setzen, wird im Wesentlichen ein decl-specifier-seq platziert, wobei der Compiler eine init-declarator-list erwartet. Wenn dieses Element fehl am Platz angezeigt wird, behandelt der Compiler die Zeile als fehlerhaft.

Die Spezifikation stellt auch fest, dass die for Schleife entspricht:

{ 
    for-init-statement 
    while (condition) { 
     statement 
     expression ; 
    } 
} 

wo condition standardmäßig auf „true“, wenn er weggelassen wird.Das Nachdenken über diese "erweiterte" Form kann hilfreich sein, um zu bestimmen, ob eine gegebene Syntax mit einer for-Schleife verwendet werden kann.

+4

Addendum: Es ist keine gültige Komma-Anweisung, WEIL die Typen in einer Komma-Anweisung (nach C die Sprachdefinition) gleich sein müssen. Derselbe Grund, warum die Komma-Anweisung 'int a = 0, int b = 0;' äquivalent zu 'int a = 0, b = 5;' ist - die Typen aller Variablen, die nach ganz links deklariert sind, werden vom ganz linken if übernommen abwesend (oder muss dasselbe sein, falls vorhanden). –

+4

Es gibt keine "Komma-Anweisung". Der Komma-Operator wird verwendet, um "Komma-Ausdrücke" zu machen, und Ausdrücke (aller Typen) sind Teile von Anweisungen. Aber das ist kein Ausdruck, und das Komma ist kein Komma-Operator. –

+0

Große Antwort, danke. Zwei Punkte: 1) Mein Compiler (g ++/Cygwin) akzeptiert keine int a = 0, int b = 0; 2) Ich dachte süffisant "Oh ja, ich weiß * was (C)", aber ich dachte, es würde dasselbe wie Perl machen. Perl würde alle durch Komma getrennten Elemente auswerten und die letzte z zuweisen. Nicht das gleiche! – Jonathan

1

Solange Sie eine gültige Anweisung mit dem Komma ,-Operator schreiben können, ist es akzeptabel.

+0

Das ist angesichts des Zusammenhangs der Frage nicht ganz genau. –

1

C++ (auch C und Java) erlauben nicht die Deklaration von mehr als einem Variablentyp im Rahmen einer for-Schleife. In der Grammatik liegt das daran, dass das Komma in diesem Kontext keine neue Anweisung startet. Effektiv ist nur eine Deklaration innerhalb der for(;;) Anweisung erlaubt. Die Begründung ist, weil diese Anforderung ziemlich ungewöhnlich ist, und Sie können es nur mit einem etwas ausführlicheren Konstrukt erhalten.

13

Es ist eigentlich eine Begrenzung der Deklarationsanweisungen:

int i=0, j=0, *k=&i;  // legal 
int i=0, double x=0.0; // illegel 

Also, im Grunde die Antwort auf Ihre letzte Frage ist: (A) & (B) sind die gleichen. (C) ist anders.

Wie BTA weist darauf hin:

z = 1,3,4; 

ist die gleiche wie

z = 1; 

Das ist jedoch wegen = eine höhere Priorität als , hat. Wenn es so geschrieben:

z = (1,3,4); 

dann wäre das das gleiche wie:

z = 4; 
+0

Vorrang! Ich war eine Weile von C entfernt und habe meine Gewohnheit, Klammern zu schreiben, "um sicher zu sein" verloren. – Jonathan

+0

Es ist keine Einschränkung von "Deklarationsanweisungen", es ist eine Einschränkung der Deklaration. Der erste Teil von 'for' ist keine Aussage für sich selbst, also hat die Sache nichts mit einer Deklaration * Aussage * zu tun. – AnT

20

Wenn Sie in mehrere Variablen unterschiedlichen Typs verwenden for-Schleife dann könnte man Strukturen wie folgt verwenden:

for(struct {int i; long i2;} x = {1, 1}; x.i2 < mid; x.i++, x.i2 = x.i * x.i) 
{ 
    cout << x.i2 << endl; 
} 

so ist dies keine Einschränkung, nur ein wenig andere Syntax verwenden.

+1

+1: Ich war gerade dabei, darüber zu schreiben ... Schade, dass VC++ es nicht unterstützt ... – dalle

+1

Dies sollte funktionieren. C++ Standard ermöglicht dies. –

+0

Ja, es sollte * funktionieren, aber dann ist VC++ nicht C++ Standard-kompatibel. Mit Comeau erfolgreich getestet. – dalle

1

Nun, ich habe mehr gegoogelt, und ich denke, die Antwort für C++ ist "für() Aussagen sind sehr spezielle Orte" Ick.

Exzerpieren von einem ISO-Spezifikation:

for (for-init-statement conditionopt ; expressionopt) statement 

wo

for-init-statement: 
expression-statement 
simple-declaration 

und sie müssen angeben, dass

[Note: a for-init-statement ends with a semicolon. ] 

So ist die C++ Syntax spec. wird speziell gehackt, so dass nur ein decl-spec (d. h. Typ) in dem ersten Slot erlaubt ist. Sieht so aus, als wären unsere Versuche, von Grundprinzipien zu argumentieren, zum Scheitern verurteilt. Danke für alle Antworten.

0

kann ich sehen, warum Sie Hoffnung, die funktionieren würde, aber --- gegeben, dass auch die eher einfältig Lehrmittel verwenden, die

for (i=0; i<max; i++){ 
    ... 
} 

zu

i=0; 
while (i<max){ 
    ... 
    i++; 
} 
entspricht

Sie Syntax funktioniert nicht --- Ich kann nicht sehen, warum Sie erwartet, dass es würde. EAch der Bits muss gültig sein.

Verwandte Themen