was bewirkt "usart_write_P(PSTR(format) , ## args"

#3671081
Lesenswert?

Hallo,

zur Zeit bin ich dabei, mich in die Dekodierung des DCF77-Signals 
einzuarbeiten und bin bei der Suche nach Vorlagen auf Ulrich Radigs 
Variante gestoßen, die eine Ausgabe auf das Terminal schreibt.

http://www.ulrichradig.de/home/index.php/avr/dcf77_uhr
http://www.ulrichradig.de/home/uploads/File/AVR_DCF77/SourceCode.zip

Kann bitte mal jemand diese beiden Zeilen erklären?

in usart.h:
#define usart_write(format, args...)   usart_write_P(PSTR(format) , ## 
args)


in main.c:
    usart_write("%i-%i-%i Time: %i:%i:%i Sync: %i  Rx: %i       \r",
        day,mon,year,hh,mm,ss,flags.dcf_sync,flags.dcf_rx);
    //Wait a schort time


mit freundlichem Gruß
#3671094
Lesenswert?

Das mit den .. bzw. ## ist eine gcc-Erweiterung, die variable 
Argumentanzahl auch für #defines erlaubt. Sinnvoll ist das im 
wesentlichen für printf-Verwandte (wie das usart_write). Der erste 
Parameter des Makros ist der Formatstring, alle weiteren Argumente 
werden mit .. zusammengefasst und im Makrokörper mit ## wieder am Stück 
verwertet.

Der gcc hat übrigens eine ganze Menge Erweiterungen. Solange man in der 
gcc-Welt bleibt (beim AVR noch eher als sonst ;) ist es auch durchaus 
sinnvoll, sich die mal zumindest anzuschauen.

http://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html

Das mit dem ../## fällt unter "Variadic Macros".
Persönliche Seite #3672236
Lesenswert?

Christian S. schrieb:
> in usart.h:
> #define usart_write(format, args...)   usart_write_P(PSTR(format) , ##
> args)

Wichtig ist dabei, daß nach ## kein Zeilenumbruch erfolgt, also
1
#define usart_write(format, args...)   usart_write_P(PSTR(format) , ##args)

Eine weitere GCC-Spezialität ist das Leerzeichen vor dem Komma.  Es 
bewirkt die Entfernung des nachfolgenden Kommas für den Fall, daß keine 
weiteren Argumente folgen.

Damit funktioniert dann auch Code wie usart_write ("Hallo") der zu 
usart_write_P (PSTR("Hallo")) expandiert (*) und eben nicht zu 
usart_write_P (PSTR("Hallo") ,) was einen Compilerfehler nach sich zöge.

Variadische Makros gibt's auch ab C99, allerdings mit anderer Syntax.

(*) Der Übersichtlichkeit wegen ohne expandiertes PSTR Makro.
#3672341
Lesenswert?

Danke für die Zuschriften. Na, da hat unser geschätzter Ulrich aber 
mächtig in die Trickkiste gegriffen :-) Und eine Funkuhr mit einem 
variadic macro innen drin hat auch nicht jeder...

Variadic Macros != vedische Mythen sind für mich ein neues 
Experimentierfeld, für die man sich doch mal ein eigenes
Übungsprogramm gönnen könnte.
"Variadic Macros: Macros with a variable number of arguments. "

Für jedes

%i

soll anscheinend dann eine der aufgezählten Variablen

day,mon,year,hh,mm,ss,flags.dcf_sync,flags.dcf_rx

der Reihe nach eingesetzt werden, wobei in der Ausgabe noch zusätzlich 
die Worte "Time:" "Sync:" "RX:" erscheinen sollen. Richtig?


Ich melde mich nochmals, wenn es neue Ergerbnisse gibt. Beispielsweise 
könnte man direkt "AVR_DCF77/SourceCode.zip" einmal ausprobieren.



> //Wait a schort time
Den Tapsfühler habe ich zur Belustigung extra mit aus dem Quelltext 
kopiert.


mit freundlichem Gruß
#3672396
Lesenswert?

Christian S. schrieb:
> Danke für die Zuschriften. Na, da hat unser geschätzter Ulrich
> aber
> mächtig in die Trickkiste gegriffen :-) Und eine Funkuhr mit einem
> variadic macro innen drin hat auch nicht jeder...

Nun ja, das ist halt eine Möglichkeit, einen Quelltext auf verschiedene 
Microcontroller anzupassen.

> Variadic Macros != vedische Mythen sind für mich ein neues
> Experimentierfeld, für die man sich doch mal ein eigenes
> Übungsprogramm gönnen könnte.

Ganz ehrlich: die Dinger gehören zu den C-Spezial-Schweinereien, die man 
erst dann anschauen sollte, wenn man normales C mit all seinen Facetten 
wirklich, wirklich, wirklich kann.

Oliver

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