Forum: Compiler & IDEs C-Präprozessor


von Gast (Gast)


Lesenswert?

Ich mache in meinem Code ein paar Berechnungen mit dem C-Präprozessor. 
Gibt es eine einfache Möglichkeit, die Ergebnisse (also den Inhalt von 
Makros) auszugeben.

Bekannt ist mir die Methode, Makros mit dem gdb zu evaluieren. Kann man 
die Inhalte von Makros nicht irgenwie beim Compilieren ausgeben (ähnlich 
wie mit Texten bei #error oder #warning)?

Vielen Dank im Voraus für eure Antworten.

von (prx) A. K. (prx)


Lesenswert?

Eher nicht, denn ich bezweifle mal, dass du tatsächlich irgendwas mit 
dem Präprozessor berechnest. Die einzige Stelle wo der selber rechnet 
ist das #if Statement.

von gast (Gast)


Lesenswert?

cpp ist dein freund, oder -E bei CC.

von Naja (Gast)


Lesenswert?

Es gibt bei den meisten Compilern einen Startparameter, der es erlaubt 
nur die Präprozessor Makros zu expandieren.
Das ergibt zwar nicht das selbe Verhalten wie bei #error oder #message 
sollte aber helfen.

von Sven P. (Gast)


Lesenswert?

Der Präprozessor ist so ein Ding, das man vor 15 Jahren schon hätte 
wegwerfen sollen. Wenn möglich, berechne lieber in C und vertrau ein 
ganz klein wenig auf die Fähigkeiten des Optimierers.

von (prx) A. K. (prx)


Lesenswert?

Sven P. schrieb:

> Wenn möglich, berechne lieber in C und vertrau ein
> ganz klein wenig auf die Fähigkeiten des Optimierers.

Ich bin ziemlich sicher, dass er genau das tut, ohne es zu wissen ;-).

von Gast (Gast)


Lesenswert?

@A. K.: Genau um das #if-Statement geht es mir. Ich mache eine kleine 
Berechnung ähnlich der in der avr-libc zum Baudraten-Fehler und möchte 
eine Warnung ausgeben.

Zur Kontrolle hätte ich  halt gerne, den berechneten Wert mit der 
Warnung ausgegeben.

von zwieblum (Gast)


Lesenswert?

#define BAUD 115200UL

#if F_CPU < 2000000UL && defined(U2X)
    UCSR0A = _BV(U2X);                   // improve baud rate error by 
using 2x clk
    UBRR0L = (F_CPU / (8UL * BAUD)) - 1;
#else
    UCSR0A = 0;
    UBRR0L = (F_CPU / (16UL * BAUD)) - 1;
#endif
    UCSR0B = _BV(TXEN0)  | _BV(RXEN0);   // tx/rx enable
    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);  // 8 Bit

#define UBRR_VAL   ((F_CPU+BAUD*8)/(BAUD*16)-1)
#define BAUD_REAL  (F_CPU/(16*(UBRR_VAL+1)))
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)

#if ((#BAUD_ERROR > 10) || (#BAUD_ERROR < -10))
#error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit 
zu hoch!"
#endif

und oh wunde der präprozessor rechnet doch ...

von Gast (Gast)


Lesenswert?

@zwieblum: Eben!

Kleine Nebenfrage zu:
#if ((#BAUD_ERROR > 10) || (#BAUD_ERROR < -10))

Was bewirkt die # vor BAUD_ERROR? Ist die zwingend notwendig?

von (prx) A. K. (prx)


Lesenswert?

zwieblum schrieb:

> und oh wunde der präprozessor rechnet doch ...

Im #if tut er das, das hatte schon geschrieben, aber er tut es nur dort. 
Überall sonst reicht er die Rechnung 1:1 an den Compiler weiter.

von (prx) A. K. (prx)


Lesenswert?

zwieblum schrieb:

> und oh wunde der präprozessor rechnet doch ...

Hast du diesen Code mal ausprobiert?
Beispielsweise mit F_CPU=1000000 und GCC.

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


Lesenswert?

Gast schrieb:

> Gibt es eine einfache Möglichkeit, die Ergebnisse (also den Inhalt von
> Makros) auszugeben.

gcc -E -dM

Gibt allerdings nur den Wert am Schluss aus, wenn ein Makro zwischen-
zeitlich verschiedene Werte hat, kann man das damit nicht verfolgen.

Ansonsten erfindest du natürlich das Fahrrad nur gerade zum 42. Mal,
siehe <util/setbaud.h>.

von Gast (Gast)


Lesenswert?

@Jörg: Die Baudratenrechnung hatte ich nur als Beispiel genommen, weil 
ich bei meiner Rechnung analog vorgehe und die jeder kennen duerfte. 
Meinen Anwendungsfall habe ich nicht gepostet, um Diskussionen über Sinn 
und Zweck zu vermeiden. setbaud.h nutze ich ;)

Aber um mal bei dem Beispiel von Zwieblum zu bleiben:
Wenn BAUD_REAL und BAUD definiert sind, wie kann ich das Ergebnis von

#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)

anzeigen lassen? BAUD_ERROR wird ja nur vom Präprozessor in einer 
#if-Direktive ausgewertet.

gcc -E -dM scheint da nicht zu helfen.

Danke.

von (prx) A. K. (prx)


Lesenswert?

long x = BAUD_ERROR;

gcc -S source.c

und im Resultat nach dem Initialisierungswert der Variable suchen.

Kleiner Nachteil: Der Wert stammt vom Compiler, nicht vom Präprozessor. 
Die können unterschiedlicher Ansicht sein weil unabhängig voneinander 
ausgewertet (sollten zwar nicht, aber...).

von Gast (Gast)


Lesenswert?

@A.K.: Danke. So habe ich mir bisher geholfen. Allerdings den Wert von x 
dann im gdb angeschaut. So ist aber nochmal einfacher.

Scheint wohl keine einfachere Moeglichkeit zu geben. Vielen Dank an 
alle.

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.