Forum: Compiler & IDEs Was macht der Compiler bei Rechnungen mit defines?


von Korlop (Gast)


Lesenswert?

Hallo!

Kurze Frage:
Wenn ich zwei Defines anlege
1
#define a 10
2
#define b 2
und im Code sowas steht:
1
if(c == (a/b))
2
{
3
  ...
4
}
steht da ja eigentlich
1
if(c == (10/2))
2
{
3
  ...
4
}
.
Ist der Kompiler so schlau und macht daraus
1
if(c == 5)
2
{
3
  ...
4
}
,
oder rechnet der Prozessor jedes mal 10 / 2 und kommt dabei auf's 
gleiche Ergebnis?

Danke für die Beantwortung meiner Frage.

Gruß
Korlop

von Christian B. (casandro)


Lesenswert?

Hängt vom Compiler ab. Ich bin mir sicher der gcc rechnet das beim 
Kompilieren aus.
Bei kommerziellen Compilern steht in der Regel im Werbeprospekt ob er 
das macht oder nicht. Aber ich denke mal, dass machen die meisten 
inzwischen.

von Obercompiler (Gast)


Lesenswert?

#define hat noch kein Compiler dieses Planeten jemals zu sehen bekommen.

von Korlop (Gast)


Lesenswert?

Obercompiler schrieb:
> #define hat noch kein Compiler dieses Planeten jemals zu sehen bekommen.
Okay, das macht der Präprozessor, aber das stand ja auch gar nicht in 
der Frage. Sondern ob der Kompiler (10/2) ausrechnet, oder nicht.
Oder macht das auch der Präprozessor

von (prx) A. K. (prx)


Lesenswert?

Ich wüsste nicht, dass der Compiler per Standard gezwungen wäre, den 
Ausdruck in jedem Fall selbst zu berechnen. Man darf aber davon 
ausgehen, dass jeder halbwegs ernst zu nehmende Compiler es tut. Zumal 
es in der Sprache andere Stellen gibt, wo er es per Standard tun muss 
(z.B. "case" Labels, Array-Deklarationen).

Korlop schrieb:
> Oder macht das auch der Präprozessor

Der Präprozessor macht eine reine Textersetzung. Einzig beim der 
Ausdruck vom #if Statement rechnet er selbst.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Die Antwort lautet (wie so oft): Es kommt drauf an :-)

Normalerweise eliminiert der Compiler das im Zuge des sogenannten 
"Constant Folding" (so nennt sich dieser Teil der Optimierung).

Aber: Es gibt Fälle, speziell im floating point bereich, wo das Ergebnis 
von der Art der Rundung abhängt, welche zur Compile-zeit möglicherweise 
unbekannt ist. Damit kann das Konstrukt 10.0 / 3.0 NICHT zur 
Compile-Zeit eliminiert werden.

von Rolf Magnus (Gast)


Lesenswert?

A. K. schrieb:
> ch wüsste nicht, dass der Compiler per Standard gezwungen wäre, den
> Ausdruck in jedem Fall selbst zu berechnen.

Gezwungen wird er grundsätzlich nie. Er darf es auch gerne immer zur 
Laufzeit machen, sofern das Verhalten des Programms gleich bleibt.

> Man darf aber davon ausgehen, dass jeder halbwegs ernst zu nehmende
> Compiler es tut. Zumal es in der Sprache andere Stellen gibt, wo er es
> per Standard tun muss (z.B. "case" Labels, Array-Deklarationen).

Ja, und es wäre jetzt irgendwie unsinnig, wenn der Compiler sich extra 
die Mühe machen würde, dort, wo das Ergebnis keine Konstante sein muß, 
die Berechnung auf die Laufzeit zu verschieben.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Korlop schrieb:
> Obercompiler schrieb:
>> #define hat noch kein Compiler dieses Planeten jemals zu sehen bekommen.

Stimmt so auch nicht.  DWARF-3 erlaubt es zum Beispiel, durch Makros zu 
debuggen, d.h. die Debug-Information muss das Makro kennen, d.h. der 
Compiler sieht das Makro auch.  Richtig ist, daß er mit der Information 
nichts weiter macht als Debug-Info zu erzeugen.

> Okay, das macht der Präprozessor, aber das stand ja auch gar nicht in
> der Frage. Sondern ob der Kompiler (10/2) ausrechnet, oder nicht.

Ja (bei GCC).

> Oder macht das auch der Präprozessor

Nein.  Der macht Textersatz.  Ist "10/2" der gleiche Text wie "5"?

Um das Prä-Compilat erzeugen (bzw. nicht löschen zu lassen) geht mit GCC 
etwa

gcc -g3 -save-temps main.c

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Johann L. schrieb:
>>> #define hat noch kein Compiler dieses Planeten jemals zu sehen bekommen.
>
> Stimmt so auch nicht.

Eben.  Das preprocessing wird vom Standard als Teil der Kompilierung
betrachtet (und dabei noch in weitere Phasen unterteilt), und auch der
GCC hat seit geraumer Zeit keinen separaten Präprozessor mehr (*),
sondern nur noch eine Bibliothek dafür.  Kann man sich ansehen, wenn
man ihn mit -v startet, da wird kein Backend-Tool namens cpp gestartet,
sondern sofort der cc1.

(*) Zumindest keinen, der als eigenständiges Binary regulär während
einer Kompilierung angeworfen wird.  Es gibt nach wie vor ein
Frontend-Kommando cpp, welches ein Nutzer aktivieren kann, um die
reine Textersetzung des Präprozessors für anderweitige Aufgaben nutzen
zu können.

von Francesco (Gast)


Lesenswert?

Nö muss der compiler sowas nicht machen/können:


1) Ist es ein anweisung d.h. es handelt sich um ein Expression die wird 
nicht in die zahl "5" umgewandelt sonder in ein opcodes (für die FPU) 
und die wird jedesmal ausgeführt die operation.

2) Ist schlechter programmierstil sowas zu machen :)


Lösung:

Um die zahl 5 wie du dir es vorstellst zu erhalten müsstest du folgendes 
machen:

#define a
#define b
#define val (a / b)

somit hättest du die zahl 5, siehe, Präprozessor funktionsweise.

Gruß
Francesco

von Stefan W. (dl6dx)


Lesenswert?

Francesco schrieb:
> Um die zahl 5 wie du dir es vorstellst zu erhalten müsstest du folgendes
> machen:

Das ist nur ein weiteres Makro, das expandiert wird. Aus
1
#define a 10
2
#define b  2
3
#define val (a / b)
4
5
if ( c == val)
6
  {
7
8
  }

wird letztendlich auch
1
if ( c == (10 / 2))
2
  {
3
4
  }

Grüße

Stefan

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.