assoziativität, undefinded behaivour

Gast #717008
Lesenswert?

<ccode>
#include <stdio.h>

int glob = 0;

int a(void) {
    glob = 1;
    printf("a\n");
    return 1;
}

int b(void) {
    glob = 2;
    printf("b\n");
    return 2;
}

int c(void) {
    glob = 3;
    printf("c\n");
    return 3;
}

int main() {
    printf("%i\n", glob);
    a()+b()+c();
    printf("%i\n", glob);
    return 0;
}
</ccode>

gehe ich Recht in der Annahme, dass ...

a) die Reihenfolge der Aufrufe durch Assoziativität
eindeuting festgelegt ist (+ left to right) printet
a
b
c

b) die zuweisung zu glob kein undefined behaivour provoziert, weil
Funktionsaufruf ein Sequenzpunkt ist.

c) undefined behavour wäre
glob = a() + b() + c() + ++glob;
oder wenn a einen int parameter nehmen würde
glob = a(glob++);
aber das hier ist vollkommen ok
glob = glob++, a();

möchte nur, dass ihr mich verifiziert :)

grüsse, daniel
Gast #717013
Lesenswert?

AFAIK ist das alles kein well-formed code. Bei f() + g() ist (meine ich) 
nicht festgelegt, welche Funktion zuerst aufgerufen wird. Der Compiler 
wird sich natuerlich fuer eine entscheiden, aber welche, das steht ihm 
frei.

Bei f(g(), h()) bin ich mir sogar sicher, dass nicht festgelegt ist in 
welcher Reihenfolge die Parameter ausgewertet werden.

Davon ganz abgesehen: Selbst wenn das definiert waere, wuerde ich 
solchen Code niemals schreiben. Wenn du dir schon nicht sicher bist, wie 
sollen dann andere herausbekommen was die Zeile bedeutet? Wieso nicht 
einfach ein paar sequence points setzen?

a = f();
b = g();
c = h();
d = a + b + c;
Gast #717042
Lesenswert?

Eigentlich ist der Hintergrund einfach die C und C++ Spezifikation 
aufzufrischen.
Dass die Evaluationsreihenfolge der Funktionsparameter dem Compiler
überlassen ist, das weiss ich. Ich bin mal böse auf die Schnauze
bei folgendem Code gefallen ...

#include <iostream>
#include <cstdlib>

int main() {
    int i = 0;
    std::cout << i << '\t' << ++i << std::endl;
    i = 0;
    std::cout.operator<<(i).operator<<('\t').operator<<(++i).operator<<(std: 
:endl);

    return EXIT_SUCCESS;
}

i und ++i sind hierbei ohne Sequenzpunkt auf einer Ebene sozusagen.
es ist nur weniger sichtbar wenn der Operator << heisst und nicht +

komischerweise wird '\t' als int in der 2-ten expliziten Aufrufform 
interpretiert.

grusse, daniel
Moderator Persönliche Seite #717051
Lesenswert?

daniel wrote:

> a) die Reihenfolge der Aufrufe durch Assoziativität
> eindeuting festgelegt ist (+ left to right) printet

Nein.  Assoziativität bedeutet nur, in welcher Reihenfolge die
Ergebnisse der Funktionsaufrufe bewertet werden, nicht aber, in
welcher die Funktionen aufgerufen werden.  Daher ist das Verhalten
bezüglich der Variablen glob undefined.

Es gibt nur wenige Dinge im C-Standard, die dem Compiler eine
Vorschrift auferlegen, in welcher Reihenfolge Dinge abzuarbeiten
sind.  Dazu gehört einerseits der Komma-Operator, andererseits
eine verkettete Bedingung.
Gast #717425
Lesenswert?

hmm, Danke
aber irgendwie macht es keinen Sinn für mich, vielleicht misverstehe
ich etwas. Addition ist doch eine kommutative Operation, wozu dann
die Evalutationsreihenfolge (left to right) definieren?
Es scheint für mich zumindest nur dann Sinn zu machen, wenn
die Seiteneffekte (zB durch Körper der aufgerufenen Funktionen) ins 
Spiel kommen.

grüsse, daniel
#717512
Lesenswert?

daniel wrote:

> ich etwas. Addition ist doch eine kommutative Operation, wozu dann
> die Evalutationsreihenfolge (left to right) definieren?

Wie willst du feststellen, dass die Reihenfolge left to right
bei Addition definiert ist oder nicht?

Der Compiler muss Code erzeugen, der das korrekte Ergebnis von
a + b (bei Integer) erzeugt.
Ob er das macht, indem er a in einem Register vorlegt und
in dieses Register b addiert, oder anders rum, ist völlig
dem Compiler belassen.


> Es scheint für mich zumindest nur dann Sinn zu machen, wenn
> die Seiteneffekte (zB durch Körper der aufgerufenen Funktionen) ins
> Spiel kommen.

Wenn Seiteneffekte ins Spiel kommen, ist so gut wie gar nichts
mehr garantiert. Brutal ausgedrückt.
Gast #717578
Lesenswert?

hab dazu bei Wiki nochmals explizit die Antwort gefunden
http://de.wikibooks.org/wiki/C++-Programmierung:_Ausdr%C3%BCcke_und_Operatoren

int x = (a() + b()) + c();
sehe ich das richtig, die Klammerung bleibt also genauso erfolglos?
Sie würde die Precedence von 1 Plus erhöhen, aber Reihenfolge
ist ein dazu orthogonales Konzept?

mir fällt gerade ein Vergleich ein
bei f(a(),b(),c()) .. wie die meisten in diesem Fall wissen,
kann die Reihenfolge beliebig sein.
Wenn man sich jetzt f(x,y,z) als x+y+z implementiert denkt, so
sind x,y,z nichts anderes als Parameter dieser Funktion f.
Und Parameter werden beliebig zu ihrem Wert evaluirt.
Vielleicht einwenig weithergehollt, aber als Eselsbrücke geeignet :)

grüsse, Daniel

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren