Interdependente Initialisierung mit Kommas?

8

Ist das Folgende perfekt definiert:

%Vor%

d. streng äquivalent zu:

%Vor%

EDIT: die Frage ist nicht über Stil (ich weiß, dass es falsch ist ...), die Frage ist "theoretisch"

    
Vincent 14.06.2014, 20:41
quelle

2 Antworten

8

Die richtige Antwort ist das

%Vor%

und

%Vor%

sind normalerweise äquivalent (nicht streng).

Unter Berücksichtigung des Standards § 8 Deklaratoren [dcl.decl] :

  

3 Jeder Init-Deklarator in einer Deklaration wird separat analysiert, als ob er selbst in einer Deklaration enthalten wäre.

und in der Fußnote [100] erklärt weiter:

  

Eine Deklaration mit mehreren Deklaratoren entspricht in der Regel der entsprechenden Deklarationsfolge mit jeweils einem einzigen Deklarator   Deklarator. Das ist

     

T D1, D2, ... Dn;

     

entspricht normalerweise

     

T D1; T D2; ... T Dn;

     

wobei T ein decl-specifier-seq ist und jedes Di ein init-declator ist.

  • Das obige garantiert, dass x = 42 und y = x separat ausgewertet werden. Wie jedoch @Praetorian in den Kommentaren korrekt hervorgehoben wurde, sind Fußnoten nicht normativ.

  • Dies bedeutet, dass die Reihenfolge der Bewertung nicht gut definiert ist und ein Implementierer die Auswertung der Deklarationen in umgekehrter Reihenfolge (d. h. T Dn; ...T D2; T D1; ) implementieren könnte.

  • Man könnte argumentieren, dass der Komma-Operator von links nach rechts eine Bewertung garantiert. Dies ist jedoch nicht der Fall. Laut der K & amp; R [K & amp; R II, 3.6 p.63], das gilt auch für C ++:

  
    
      

Die Kommas, die Funktionsargumente, Variablen in Deklarationen usw. voneinander trennen, sind keine Kommaoperatoren und garantieren keine Bewertung von links nach rechts.

    
  
    
101010 14.06.2014, 23:20
quelle
4

Diese Frage wurde in comp.lang.c ++. moderiert beantwortet vor langer Zeit unter dem Thema init-declarator-list Analyse-Reihenfolge und die Schlussfolgerung war Yes .

Obwohl ich das Argument full-expression sehe, sehe ich aber nicht die Reihenfolge des Bewertungsarguments. Also ich denke, das ist nicht spezifiziert.

Der relevante Teil der Frage ist:

  

In dieser Erklärung und Definition:

     

int a = 2, b = a;

     

Ist garantiert, dass b immer als 2 initialisiert wird? Wenn ja, dann   können wir sagen, dass a = 2 immer vor b = a analysiert (oder ausgewertet?) wird?

und der relevante Teil der Antwort ist:

  

Ja. Streng genommen muss das beobachtbare Verhalten des Programms sein   als ob alle Nebenwirkungen des 'a = 2' Teils der Deklaration   stattfand, bevor die Bewertung des "b = a" -Teils beginnt. (Im   In diesem einfachen Beispiel könnte natürlich ein Compiler 2 zuweisen   zu beiden a und b in beliebiger Reihenfolge oder sogar parallel, weil so   würde das gleiche beobachtbare Verhalten ergeben.)

und weiter unten:

  

In diesem speziellen Fall trennt es jedoch den Deklarator   Liste in separate Deklaratoren; Jeder Deklarator enthält ein vollständiges   Ausdruck, und die Deklaratoren werden der Reihe nach ausgewertet.

Aktualisieren

Was jeden init-declator zu einem vollständigen Ausdruck macht ist subtil, aber soweit ich das beurteilen kann, folgt er der gleichen Logik wie in Mehrere Mutationen der gleichen Variablen innerhalb des Initialisierers listet undefiniertes Verhalten vor C ++ auf 11 . In diesem Fall beginnen wir mit der Grammatik, die in ection 8 definiert ist:

%Vor%

Der nächste Schwerpunkt ist die Grammatik Initialisierer , die im Abschnitt 8.5 :

behandelt wird %Vor%

In beiden Fällen haben wir = initializer-Klausel , die uns zu Zuweisungsausdruck bringt, wenn wir der Grammatik in Abschnitt 5 folgen Zurück zu primary-expression , die uns entweder einen literalen oder ID-Ausdruck geben kann.

Also haben wir tatsächlich Voll-Ausdrücke, die durch ein grammatikalisches Komma getrennt sind, also haben wir:

%Vor%

und nach Abschnitt 1.9 paragraph 14 sehen wir Folgendes:

  

Jede mit a verbundene Wertberechnung und Nebenwirkung   Full-Expression wird vor jeder Wertberechnung und Seite sequenziert   Effekt, der mit dem nächsten zu evaluierenden Voll-Ausdruck verbunden ist. 8.

Was die Reihenfolge der Auswertung angeht, denke ich, dass dies nicht spezifiziert ist, die gleiche Logik, die für Fehlerbericht 430 für Initialisierungslisten scheint auch hier zu gelten. In C ++ 11 wurde die Sprache für Initialisierungslisten mit folgendem Zusatz im Abschnitt 8.5.4 :

festgelegt
  

Innerhalb der Initialisiererliste einer brained-init-Liste ist der   Initialisierungsklauseln, einschließlich solcher, die sich aus Pack-Expansionen ergeben   (14.5.3), werden in der Reihenfolge ausgewertet, in der sie auftreten. [...]

es gibt keine Entsprechungen für Initialisierer .

    
Shafik Yaghmour 15.06.2014 03:43
quelle