www.mikrocontroller.net

Forum: Compiler & IDEs assoziativität, undefinded behaivour


Autor: daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab dazu bei Wiki nochmals explizit die Antwort gefunden
http://de.wikibooks.org/wiki/C++-Programmierung:_A...

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
daniel wrote:
> hab dazu bei Wiki nochmals explizit die Antwort gefunden
> http://de.wikibooks.org/wiki/C++-Programmierung:_A...
>
> int x = (a() + b()) + c();
> sehe ich das richtig, die Klammerung bleibt also genauso erfolglos?

Das siehst du absolut 100% richtig.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:

> Das siehst du absolut 100% richtig.

Ergänzung: die Klammern sind ja völlig redundant, da sie nur das
ausdrücken, was ohnehin bereits der Fall ist.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.