Forum: Mikrocontroller und Digitale Elektronik #defines verschachteln


von Stephan R. (Firma: FHK) (nautosteer)


Lesenswert?

Hallo!

mein At2560 besitzt 4 UARTs. Ich moechte an einer Stelle festlegen, an 
welchem welches Gerät angeschlossen ist und dass das Makro dann von 
selbst die richtige uartX_puts - Prozedur (uart0_puts, uart1_puts, 
uart2_puts, uart3_puts verwendet.

Meine Traumvorstellung zum Senden ans Terminal ueber UART0:

#define uart_terminal 0   //terminal an UART0 angeschlossen
#define send_to_terminal  uart(uart_terminal)puts //gewaehltes uart 
eingebaut
send_to_terminal("hallo!"); //zusammengesetzt sendets zum terminal

Das funktioniert "natürlich" nicht, nur wie verschachtelt man #defines 
vernuenftig?

von Peter II (Gast)


Lesenswert?

Stephan R. schrieb:
> Das funktioniert "natürlich" nicht, nur wie verschachtelt man #defines
> vernuenftig?

http://de.wikipedia.org/wiki/C-Pr%C3%A4prozessor#Verkettung_von_Makroparametern

von Stephan R. (Firma: FHK) (nautosteer)


Lesenswert?

Bin begeistert, danke!

von Stephan R. (Firma: FHK) (nautosteer)


Lesenswert?

Meine Begeisterung hat sich gelegt:

Was tu ich falsch?
Die Beschreibung beschreibt die Verkettung von Makroparametern- ist das 
das gleiche als würde man (wie ich) Zeichenketten für den Compiler 
zusammenfügen wollen?

Nichtlaufendes Beispiel:
#define glue(a, b, c) a ## b ## c
glue(uart, 3, puts) ("hallo");

von perlbastel (Gast)


Lesenswert?

Versuch mal
1
#define glue2(a, b, c) a ## b ## c
2
#define glue(a, b, c) glue2(a,b,c)
3
glue(uart, 3, puts) ("hallo");

von Stephan R. (Firma: FHK) (nautosteer)


Lesenswert?

Läuft!
Nur warum?

von perlbastel (Gast)


Lesenswert?

Stephan R. schrieb:
> Nur warum?
Der Präprozessor ist da etwas eigen... (Anders gesagt: Ich nur dass es 
läuft aber nicht warum.)

von Stephan R. (Firma: FHK) (nautosteer)


Lesenswert?

Es bleibt ein Nachgeschmack aber für Montag nachts reichts..
Danke!

von perlbastel (Gast)


Lesenswert?

Warte mal bis Karl Heinz (Buchegger) vorbeikommt, der wird es wissen...

von Stephan R. (Firma: FHK) (nautosteer)


Lesenswert?

Der schimpft bestimmt weil mein C-Buch grad mal nicht am Platze ist

von Karl H. (kbuchegg)


Lesenswert?

perlbastel schrieb:
> Warte mal bis Karl Heinz (Buchegger) vorbeikommt, der wird es wissen...

:-)

Die Sache ist die.
Das hier
1
#define glue(a, b, c) a ## b ## c
2
glue(uart, 3, puts) ("hallo");

macht genau das, was er will.
Nur: Das hat er nicht so in seinem richtigen Code stehen. Dort steht 
eher so was wie
1
#define UART_NR  3
2
3
#define glue(a, b, c) a ## b ## c
4
glue(uart, UART_NR, puts) ("hallo");

und DAS funktioniert jetzt nicht mehr.
Warum?
Weil die Auswertereihenfolge verkehrt ist. Der Präprozessor setzt mit 
diesen Angaben einen Aufruf der Funktion
  uartUART_NRputs
zusammen. D.h. UART_NR wurde nicht ausgewertet. Und genau da kommt jetzt 
der Zwischenschritt über ein anderes Makro ins Spiel. Sein einziger 
Zweck ist es, eine Schicht einzuziehen, in der der Präprozessor 
eventuelle Argumente, die ihrerseits wieder Makros sind, ersetzen kann 
und erst DANACH das Token Pasting erfolgen soll.

#define glue(a, b, c) glue2(a,b,c)

 glue(uart, UART_NR, puts)

wird zu

 glue2( uart, UART_NR, puts )

dann werden die Argumente Makro-Ersetzt

 glue2( uart, 3, puts )

und erst danach wird wieder nachgesehen, ob es für glue2 eine 
Makroersetzung gibt.
Und dann klappts auch mit Argumenten, die ihrerseits Makros sind.

von Stephan R. (Firma: FHK) (nautosteer)


Lesenswert?

Okay, dreimal gelesen, akzeptiert.
Ist es ein Versäumnis der C-Entwicklung, diese Makro-Umsetzung 
automatisch oder per Befehl durchzuführen?


(PS: Ich hab vorm Schlafengehen immer ne Fluortablette bekommen- was hat 
KHB bekommen?)

von Karl H. (kbuchegg)


Lesenswert?

Stephan R. schrieb:
> Okay, dreimal gelesen, akzeptiert.
> Ist es ein Versäumnis der C-Entwicklung, diese Makro-Umsetzung
> automatisch oder per Befehl durchzuführen?

Nö.
Es ist einfach nur so definiert worden, dass die Argumente zu ## nicht 
vor der Zusammensetzung Makro-ersetzt werden. Das ist alles.

Ein
1
#define CHECK_AA foo
2
#define CHECK_BB bar
3
4
#define CALL_IT(nr) CHECK_ ## nr
5
6
...
7
8
  CALL_IT( AA )();

baut einen Funktionsaufruf der Funktion foo zusammen. Unabhängig davon, 
ob es davor ein
1
#define AA 5
gab oder nicht. Es hat halt immer alles 2 Seiten.

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.