Postinkrement, priorität
-
Hallo,
Ich als alter Pascal programmierer bin neu in der C Welt und muss mich durch verschiedene Bereiche kämpfen, wie jetzt zbsp:
Aufgabe:
int array[10]={1,2,3,4,5,6,7,8,9,10} int *a, *b; a=ia; *a++=7;
Es geht um die Zeile *a++=7;
Laut einer Musterlösung passiert folgendes: *a=7; und dann a++; //*a=7 bedeutet ja:ia[0]=7; und a++ bedeutet dass die Adresse um 4Bytes inkrementiert wird, also zeigt a jetzt auf ia[1]
Dann steht in der MusterLösung noch folgendes:*a++ entspricht nach der Priorität der Operatoren *(a++)
Und das ergbibt für mich kein Sinn. Da laut der Priorität wie in diesem Zitat zuerst a++ ausgeführt werden müsse, und dann *a=7, aus dem Grund da a++ in Klammern steht und Klammern ja IMMER zuerst ausgeführt werden müssten ?
Hoffe meine Frage war verständlich,
freue mich auf gute Antworten, danke Vielmals im Voraus!! (voraus mit 2 r wird mit * ersetzt :p )
-
newinc schrieb:
Hallo,
Ich als alter Pascal programmierer bin neu in der C Welt und muss mich durch verschiedene Bereiche kämpfen, wie jetzt zbsp:
Aufgabe:
int array[10]={1,2,3,4,5,6,7,8,9,10} int *a, *b; a=ia; *a++=7;
Es geht um die Zeile *a++=7;
Laut einer Musterlösung passiert folgendes: *a=7; und dann a++; //*a=7 bedeutet ja:ia[0]=7; und a++ bedeutet dass die Adresse um 4Bytes inkrementiert wird, also zeigt a jetzt auf ia[1]
Dann steht in der MusterLösung noch folgendes:*a++ entspricht nach der Priorität der Operatoren *(a++)
Und das ergbibt für mich kein Sinn. Da laut der Priorität wie in diesem Zitat zuerst a++ ausgeführt werden müsse, und dann *a=7, aus dem Grund da a++ in Klammern steht und Klammern ja IMMER zuerst ausgeführt werden müssten ?
Hoffe meine Frage war verständlich,
freue mich auf gute Antworten, danke Vielmals im Voraus!! (voraus mit 2 r wird mit * ersetzt :p )Bedenke, daß a++ zwar a erhöhet, der Wert von a++ ist aber das alte unerhöhte a.
Damit tut *a++ auch soviel wie erst *a anzuschauen und später irgendwann den Seiteneffekt des Erhöhens von a auszuführen.
Also wenn ich http://de.cppreference.com/w/cpp/language/operator_precedence anscheie, dann steht da echt *(a++). Ja, a++ wird zuerst ausgewertet (was aber ja den alten Wert ergibt). Mir scheint die Musterlösung richtig (wenn auch ein wenig verwirrend).
-
Die Priorität und die Reihenfolge der Ausführung sind zwei Dinge, die nichts miteinander zu tun haben. Die Priorität sagt dir (und besonders dem Compiler) lediglich, dass *a++ wie *(a++) zu interpretieren ist, d.h. dass der Wert des Ausdrucks a++ dereferenziert wird.
-
volkard schrieb:
Ja, a++ wird zuerst ausgewertet (was aber ja den alten Wert ergibt). Mir scheint die Musterlösung richtig (wenn auch ein wenig verwirrend).
Hab jetzt noch folgendes entdeckt:
Postfix ( a++ ) Bei der Postfix-Notation wird die Variable inkrementiert, nachdem sie verwendet wurde
Das heisst laut Priorität, wird ja zuerst a++ ausgeführt. Da dies doch ein Postifix ist, wird es erst zum Schluss "wirklich" ausgeührt, und desswegen zuerst *a und dann a++, da a ja dann verwendet wurde.
http://de.wikibooks.org/wiki/C-Programmierung:_Ausdr%C3%BCcke_und_OperatorenVersteh ich das richtig ?
-
Du kannst dir das Postinkrement als eine Funktion etwa wie (jetzt mit Integern statt Zeigern)
int postincrement(int *x) { int r = *x; *x += 1; return r; }
vorstellen. Dann ist
int x = 0; printf("%d\n", postincrement(&x)); // gibt 0 aus // Hier ist x == 1
genauso wie
int x = 0; printf("%d\n", x++); // gibt 0 aus // Hier ist x == 1
Jetzt ist mit diesen Nebeneffekten etwas Vorsicht geboten; die genauen Regeln, wann das Inkrement eingetreten sein darf und wann es eingetreten sein muss, sind recht lose gehalten, um Compilern Freiraum bei der Optimierung zu geben. Faustregel: Es ist keine gute Idee, eine Variable in einem Ausdruck zu inkrementieren/dekrementieren, in dem sie zweimal benutzt wird, denn:
int x = 0; int y = x + x++; // Wert von y ist nicht spezifiziert. some_function(x++, x); // Werte der Parameter, die an some_function übergeben werden, sind nicht spezifiziert.
"nicht spezifiziert" bedeutet hier, dass der C-Standard keine Aussage darüber macht, welche Werte die Variable annimmt, so dass das z.B. abhängig vom Compiler oder Compilerflags unterschiedlich sein kann. Das liegt daran, dass der C-Standard nicht vorgibt, in welcher Reihenfolge die Summanden bzw. Funktionsparameter ausgewertet werden. Etwa ist bei
int f(void) { putchar('f'); return 0; } int g(void) { putchar('g'); return 1; } int h(int x, int y) { puts('h'); return x + y; } ... int y = f() + g(); h(f(), g());
zwar definiert, dass y den Wert 1 hat, aber nicht ob "fgfgh", "gfgfh", "fggfh" oder "gffgh" ausgegeben wurde.
Die genaue Regelung ist beispielsweise hier beschrieben.
-
Um mal die andere Möglichkeit der Klammerung zu beleuchten :
(*a)++
Hier wird der Wert, auf den a zeigt verändert.
Was gerade mit einer Zuweisung, wie bei deinem Beispiel, undefiniertes Verhalten ergibt:(*a)++=7; // undefiniertes Verhalten (UB)
-
DirkB schrieb:
Um mal die andere Möglichkeit der Klammerung zu beleuchten :
(*a)++
Hier wird der Wert, auf den a zeigt verändert.
Was gerade mit einer Zuweisung, wie bei deinem Beispiel, undefiniertes Verhalten ergibt:(*a)++=7; // undefiniertes Verhalten (UB)
Das Ergebnis des Postinkrements ist ein rvalue, das sollte also gar nicht erst kompilieren.
-
Hi,
die Pioritäten bzw. Klammern besagen nur, in welcher Reihenfolge die Teilausdrücke evaluiert werden. Wann der Increment bzw. der Dekrement erfolgt, hat damit nichts zu tun.
Der Wert von a++ ist IMMER a Der Wert von ++a ist IMMER a+1 auch wenn da noch Klammern drumherum stehen.