Programmier Quiz

Gast #1966625
Lesenswert?

>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...
Gast #1966713
Lesenswert?

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.
Gast #1966730
Lesenswert?

Ich hab mir das nochmal angeschaut, scheint mit dem oft gelobten / 
verfluchten Kommaoperator und der Operatorenpriorität zutun zu haben...

Aus
1
c=MUL(2+ 3, 2 + 4);
macht der Präprozessor
1
c=(a, b) -a*b- (2+ 3, 2 + 4);
.
Wenn man die Variablen "auflöst" gibt das
1
c=(1, 2) -1*2- (2+ 3, 2 + 4);
was das gleiche Ergebnis wie
1
c=(2) -1*2- (2 + 4);
oder "schöner" formatiert
1
c = 2 - 1 * 2 - (2 + 4);
liefert.

Wenn man die Klammern wegnimmt
1
c=1, 2 -1*2- 2+ 3, 2 + 4;
compiliert das ganze noch, liefert aber ein falsches Ergebnis (1).

Komische Sache dieses "C"!
Gast #1966856
Lesenswert?

Bei
1
#define MUL (a, b) -a*b-
2

3
int a = 1;
4
int b = 2;
5
int c = MUL(2+ 3, 2 + 4);

macht der Präprozessor aus der letzten Zeile
1
int c = (a, b) -a*b-(2+ 3, 2 + 4);

die wie folgt ausgewertet wird
1
int c = (a, b) -a*b-(2+ 3, 2 + 4);
2
// 1:    -  -        ----  -----
3
//       a  b         5     6
4
// 2:   ------       ------------
5
//         b                6
6
// 3:           ---
7
//               2
8
// 4:      ------------------
9
//         2   - 2 -        6
10
// 5:      ------------------
11
//                   -6

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.
Gast #1966874
Lesenswert?

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.
Gast #1967338
Lesenswert?

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
Gast #1967514
Lesenswert?

Übersehe ich hier etwas? Bei mir gibt
1
#include <stdio.h>
2
#include <stdlib.h>
3

4
#define min(a,b) ( (a < b) ? (a) : (b) )
5

6
int main()
7
{
8
  int a, b, c;
9

10
  a = b = 1;
11
  c = min(++a,++b);
12

13
  printf("a=%d b=%d c=%d\n", a, b, c);
14

15
  return EXIT_SUCCESS;
16
}

das Ergebnis
1
> gcc -g -O0 -std=c89 test.c && ./a.out
2
a=2 b=3 c=3

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.

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