2010-06-07 5 views
9

Ich habe einige C-Code:Reihenfolge der Operationen für Pre-Inkrement und Post-Inkrement in einem Funktionsargument?

main() 
{ 
    int a=1; 
    void xyz(int,int); 

    xyz(++a,a++);  //which Unary Operator is executed first, ++a or a++? 

    printf("%d",a); 
} 
void xyz(int x,int y) 
{ 
    printf("\n%d %d",x,y); 
} 

Die Funktion xyz hat zwei übergebenen Parameter in, ++a und a++. Kann jemand die Reihenfolge der Operationen erklären, um das Ergebnis zu erklären?

Der obige Code gibt "3 13" oder "2 23" aus, je nachdem, welcher Compiler verwendet wird.

+1

Es wäre wahrscheinlich klarer, wenn Sie in Ihrem Beispielprogramm verschiedene Variablen verwendet hätten. Außerdem sollten Sie "\ n" * nach * die Werte, die Sie drucken, nicht vorher eingeben. Dies wird derzeit gedruckt "2 23" – DevinB

+0

Sie sollten etwas versuchen, das klarer ist. Diese Syntax ist für einen Menschen ziemlich seltsam. Machen Sie den Code einfach, versuchen Sie nicht, komplizierte Sachen zu schreiben. – INS

Antwort

26

Nun gibt es zwei Dinge mit Ihrem Beispielcode zu beachten:

  1. Die Reihenfolge der Auswertung von Funktionsargumenten ist nicht spezifiziert, so ob ++a oder a++ ausgewertet wird zuerst ist abhängig von der Implementierung.
  2. Wenn Sie den Wert a mehr als einmal ohne Sequenzpunkt zwischen den Änderungen ändern, führt dies zu einem undefinierten Verhalten. Daher sind die Ergebnisse Ihres Codes nicht definiert.

Wenn wir den Code vereinfachen und die nicht näher bezeichnet und nicht definiertes Verhalten entfernen, dann können wir die Frage beantworten:

void xyz(int x) { } 

int a = 1; 
xyz(a++); // 1 is passed to xyz, then a is incremented to be 2 

int a = 1; 
xyz(++a); // a is incremented to be 2, then that 2 is passed to xyz 
+0

Stimmt es im zweiten Fall, dass 'a' aktualisiert wird, bevor die Funktion aufgerufen wird? Ich kenne das Ergebnis des * Ausdrucks * '++ a' ist 2, was an" xyz "übergeben wird, aber mein Verständnis war, dass der Nebeneffekt nicht unbedingt angewendet werden muss, bevor die Funktion aufgerufen wird. –

+2

@John: Ja: Es gibt einen Sequenzpunkt nach der Auswertung aller Argumente für eine Funktion, aber bevor die Funktion aufgerufen wird. –

9

Zitiert Kernighan & Ritchie, Kapitel 2.12:

Die Reihenfolge, in Welche Funktionsargumente ausgewertet werden, ist nicht angegeben, so dass die Anweisung

printf("%d %d\n", ++n, power(2, n)); /* WRONG */ 

kann unterschiedliche Ergebnisse mit verschiedenen Compilern erzeugen, abhängig von , ob n erhöht wird, bevor die Stromversorgung aufgerufen wird. Die Lösung ist natürlich

++n; 
printf("%d %d\n", n, power(2, n)); 

Funktionsaufrufe, verschachtelte Zuordnung Anweisungen und Schrittweite und Dekrementoperatoren Ursache `` Seite Effekte ‚‘ zu schreiben - eine Variable als Nebenprodukt geändert wird der Auswertung von ein Ausdruck. In jedem Ausdruck mit Nebenwirkungen kann subtile Abhängigkeiten in der Reihenfolge in welche Variablen, die an der Ausdruck teilnehmen aktualisiert werden. Eine unglückliche Situation wird durch die Aussage typisiert

a[i] = i++; 

Die Frage ist, ob der Index ist der alte Wert von i oder die neuen. Compiler können dies in verschiedene Möglichkeiten interpretieren, und generieren unterschiedliche Antworten in Abhängigkeit von ihrer Interpretation. Der Standard lässt absichtlich die meisten derartigen Angelegenheiten nicht spezifiziert. Wenn Nebeneffekte (Zuordnung zu Variablen) in einem Ausdruck stattfinden, wird die Diskretion des Compilers überlassen, da die beste Reihenfolge stark von Maschine Architektur abhängt.(Der Standard ist angeben, dass alle Nebenwirkungen auf Argumente wirksam werden, bevor eine Funktion aufgerufen wird, aber das wäre nicht Hilfe bei dem Anruf über printf). Die Moral ist, dass das Schreiben von Code, dass auf Reihenfolge der Auswertung hängt ist eine schlechte Programmierpraxis in irgendeiner Sprache. Natürlich ist es notwendig zu wissen, welche Dinge zu vermeiden, aber wenn Sie nicht wissen, wie sie auf verschiedenen Maschinen getan werden, werden Sie nicht versucht werden , um eine bestimmte Implementierung zu nutzen.

2

unärer Operator-Bewertungs-Sequenz für eine Funktion:

#include <stdio.h> 

void xyz(int x, int y) { 
    printf("x:%d y:%d ", x, y); 
} 

main() { 
    int a; 
    a=1; xyz(++a, a);  printf("a:%d\n", a); 
    a=1; xyz(a, a++);  printf("a:%d\n", a); 
    a=1; xyz(++a, a++);  printf("a:%d\n", a); 
} 

ausgeben wird

x:2 y:2 a:2 
x:2 y:1 a:2 
x:3 y:1 a:3 

Auf meinem System. Dies zeigt an, dass der zweite Parameter der Funktion zuerst ausgewertet wird. Sie sollten sich nicht auf die Reihenfolge der Auswertung von Funktionsparametern verlassen. Es ist nicht definiert, also wird es auf verschiedenen Systemen anders sein.

Gute Arbeit bei der Suche nach einem nützlichen Beispiel für dieses Verhalten.

-1

Für Uniary-Operatoren gibt es das Vorinkrement (++ i) und das Postinkrement (i ++). Bei der Vorinkrementierung wird der zu inkrementierende Wert vor einer Operation hinzugefügt. Zum Beispiel:

#include <iostream> 
using namespace std; 

void main() 
{ 
    int i = 0; 
    cout << ++i; 
} 

In diesem Fall würde die Ausgabe 1. Die Variable sein, ‚i‘ durch den Wert von 1, bevor anderen Operationen inkrementiert wurde d.h. ‚cout < < ++ i‘.

Nun, wenn wir den Post-Zuwachs in der gleichen Funktion haben:

#include <iostream> 
using namespace std; 

void main() 
{ 
    int i = 0; 
    cout << i++; 
} 

Der Ausgang wäre nur 0. Dies liegt daran, dass der Zuwachs nach der Operation passieren würde. Aber da du zu dem Übergeben sie als Parameter wissen wollen, das ist, wie es geht:

#include <iostream> 
using namespace std; 
// Function Prototypes 
void PrintNumbers(int, int); 

void main() 
{ 
    int a = 0, b = 0; 
    PrintNumbers(++a, b++); 
} 

void PrintNumbers(int a, int b) 
{ 
    cout << "First number: " << a << endl; 
    cout << "Second number: " << b << endl; 
} 

Wenn in diesen Variablen als Parameter übergeben, würde der Ausgang sein:

First number: 1 
Second number: 0 

ich diese Hoffnung hilft !!