Hallo.
Kleines Quiz:
#define MUL(a, b) a * b
int c = MUL(2+ 3, 2 + 4);
Frage: Was ist das Ergebnis für c?
Was interessant wäre:
Wie lang habt ihr für die richtige Antwort gebraucht?
Gruß
Christian
>Die Frage ist natürlich, warum?
Das ist eine gute Frage! Das originale Rätsel ist ja gerade zu trivial,
dieses hier ist es deutlich weniger. Man beachte das Leerzeichen hinter
MUL, ohne compiliert das schon mal nicht. Hab mal geguckt was der
Präprozessor von GCC da bastelt, kann das aber nicht nachvollziehen, ich
komme auf -5 oder 1. Sehr komisch...
Damit hält sich der GCC gar nicht lange auf. Der optimiert das einfach
weg.
00000088 <main>:
int main(void)
{
int c = MUL(2+ 3, 2 + 4);
Initialize();
88: f1 df rcall .-30 ; 0x6c <Initialize>
8a: ff cf rjmp .-2 ; 0x8a <main+0x2>
0000008c <SetDAC>:
}
Wenn du Code sehen willst, musst du den Wert natürlich noch verwenden.
Es geht aber nicht darum, den fertigen Wert ausgespuckt zu bekommen,
sondern wie es dazu kommt, also warum zum Schluß ein bestimmter Wert
erscheint.
User schrieb:> Deswegen schreibt man auch> #define MUL(a, b) (a)*(b)
Nur wenn man es immer noch nicht kapiert hat. Denn sonst schriebe man:
#define MUL(a, b) ((a)*(b))
User schrieb:> Deswegen schreibt man auch>> #define MUL(a, b) (a)*(b)
Um genau zu sein, schreibt man sogar
1
#define MUL(a, b) ((a)*(b))
Das Ergebnis in Klammern zu setzen, verhindert Fehler wie (am Beispiel
von ADD(a,b) := ((a)+(b))): ADD(1,2)*3. Ohne Klammern wäre dies
(1)+(2)*3 = 7, mit Klammern korrekterweise ((1)+(2))*3 = 9.
Auch bei MUL sind die Klammern außenrum nötig, da es auch Operatoren mit
höherer Präzedenz als "*" gibt, nämlich (in C) z.B. unäres "+"/"-", oder
Adress- und Dereferenzoperator "&" bzw. "*", oder "++"/"--", oder
Array-Zugriff "[]", oder Funktionsaufruf "()", usw.
1: Zuerst werden die Klammern ausgewertet.
2: Der Komma-Operator bewirkt, daß Wert und Typ
des Ausdrucks dem letzten Teilausdruck entsprechen.
3: Multiplikation hat die höchste, verbleibende Priorität.
4: Es verbleiben nur noch Subtraktionen.
5: Ergebnis is -6.
Die niedrigste Priorität hat der Zuweisungsoperator, dieser wird als
letztes berücksichtigt und somit am Ende der Variablen c der Wert -6
zugewiesen.
A. K. schrieb:> User schrieb:>>> Deswegen schreibt man auch>> #define MUL(a, b) (a)*(b)>> Nur wenn man es immer noch nicht kapiert hat. Denn sonst schriebe man:> #define MUL(a, b) ((a)*(b))
Ich hatte noch überlegt, aber dann entschieden, dich nicht damit auch
noch zu überfordern.
Klaus Wachtler schrieb:> Wenn du Code sehen willst, musst du den Wert natürlich noch verwenden.>> Es geht aber nicht darum, den fertigen Wert ausgespuckt zu bekommen,>> sondern wie es dazu kommt, also warum zum Schluß ein bestimmter Wert>> erscheint.
Das war mir schon klar. Wenn man die Variable volatile deklariert ist
das Ergebnis übrigends 12
mfg.
Zu:
#define MUL (a, b) -a*b-
Die obige define Direktive wird übrigens nicht von allen Compilern
unterstützt.VisualStudio,GCC könnens, spezifische Compiler wie
Cross Compiler oder andere nicht. Meckern tun sie alle bei b-.
Gruß
Christian
Zuerst wird die Bedingung (++a < ++b) ausgewertet. Dabei zuerst auf
beiden Seiten des Vergleichs die Inkrementierung durchgeführt. Die
Variablen a und b besitzen damit zu dem Zeitpunkt jeweils beide den Wert
2. Der Vergleich, ob a kleiner b ist, schlägt damit fehl. Dadurch wird
also der nicht-wahr-Zweig des ternären Operators ausgewertet, also b
noch einmal inkrementiert. Dieser neue Wert von b, also 3, wird nun der
Variablen c zugewiesen.
Christian schrieb:> Clown hat recht:> b und c haben am Ende 3 -> b==c==3> a wird nur einmal inkrementiert-> also a==2
Wobei ein fieser Nebenschauplatz an der Situation darin besteht, dass
auch der Fall möglich ist, dass hinten nach a gleich c ist und b nur
einmal inkrementiert wird. Je nach den konkreten Werten für a und b