Makros definieiren
-
Servus,
ist es möglich, die folgende Methode durch ein Makro zu ersetzen?
void uart_put_string (char *data_string) { while(*data_string) Usart_Tx(*(data_string++)); }
Irgendwie gibt es Probleme mit dem Leerzeichen zwischen 'r' und '*'. Beispiel:
#define uart_put_string (char *data_string) ...
Gruss
Hauser
-
Bei einem Makro brauchst du den Typen nicht - das Makro wird ersetzt, bevor der Compiler sich um solche kümmert. Denkbar wäre
#define uart_put_string(data_string) do { \ while(*(data_string)) Usart(*(data_string)++); \ } while(0)
Das do-while-Konstrukt dient dabei nur dazu, dass ein Semikolon nach einem "Aufruf" notwendig wird, das ganze also mehr wie eine Funktion aussieht. Aber Vorsicht: Ein Makro macht reine Textersetzung, wenn du also beispielsweise
uart_put_string(++foo);
schreibst, wird daraus
do { while(*(++foo)) Usart(*(++foo)++); } while(0);
Ich bin grad nicht sicher, ob das kompiliert oder nachher einfach nur Blödsinn macht. Warum willst du da überhaupt ein Makro haben? Ich sehe nichts, was hier gegen eine Funktion spricht.
-
Definiere die Funktion doch als
inline
.Oder schalt die Optimierung an.
Der Compiler entscheidet dann selber ob er die Funktion alsinline
nimmt oder nicht.
-
Ist nicht möglich ohne (wahrscheinlich unerwünschte) Nebenwirkung, dass der Zeiger nach Aufruf der Funktion unverändert ist, nach einem herkömmlich gestalteten Makro höchstwahrscheinlich aber verändert ist.
-
Ah, guter Punkt -- an die Nebenwirkung hatte ich gar nicht gedacht. Möglich ist es aber durchaus, sie zu vermeiden:
#define uart_put_string(data_string) do { \ char const *uart_put_string_intern_p = data_string; \ while(*uart_put_string_intern_p) Usart(*uart_put_string_intern_p++); \ } while(0)
-
Das funktioniert auch erst ab C99.
Nochmal:
ISO/IEC 9899:201x schrieb:
A function declared with an inline function specifier is an inline function. Making a function an inline function suggests that calls to the function be as fast as possible.
The extent to which such suggestions are effective is implementation-defined.Lass das den Compiler machen.
-
seldon schrieb:
Ah, guter Punkt -- an die Nebenwirkung hatte ich gar nicht gedacht. Möglich ist es aber durchaus, sie zu vermeiden:
#define uart_put_string(data_string) do { \ char const *uart_put_string_intern_p = data_string; \ while(*uart_put_string_intern_p) Usart(*uart_put_string_intern_p++); \ } while(0)
Warum do-while und nicht if?
-
jkljkl schrieb:
seldon schrieb:
Ah, guter Punkt -- an die Nebenwirkung hatte ich gar nicht gedacht. Möglich ist es aber durchaus, sie zu vermeiden:
#define uart_put_string(data_string) do { \ char const *uart_put_string_intern_p = data_string; \ while(*uart_put_string_intern_p) Usart(*uart_put_string_intern_p++); \ } while(0)
Warum do-while und nicht if?
Weil der Compiler das Muster erkennt und NICHT rumwarnt mit "condition is alsways false" oder so Sprüchen.
-
volkard schrieb:
jkljkl schrieb:
Warum do-while und nicht if?
Weil der Compiler das Muster erkennt und NICHT rumwarnt mit "condition is alsways false" oder so Sprüchen.
Glaub ich nicht. Der Grund ist, dass man bei do-while am Ende zwingend ein Semikolon braucht.
-
Bashar schrieb:
Glaub ich nicht. Der Grund ist, dass man bei do-while am Ende zwingend ein Semikolon braucht.
#include <stdio.h> void Usart(char ch){ } #define uart_put_string1(data_string) do { \ char const *uart_put_string_intern_p = data_string; \ while(*uart_put_string_intern_p) Usart(*uart_put_string_intern_p++); \ } while(0) #define uart_put_string2(data_string) if(1) { \ char const *uart_put_string_intern_p = data_string; \ while(*uart_put_string_intern_p) Usart(*uart_put_string_intern_p++); \ } else ((void)0) #define uart_put_string2(data_string) if(1) { \ char const *uart_put_string_intern_p = data_string; \ while(*uart_put_string_intern_p) Usart(*uart_put_string_intern_p++); \ } else switch(0) break int main(void) { if(1) { uart_put_string1("hallo") printf("test"); uart_put_string2("hallo") printf("test"); } return 0; }
Was mich wundert, ist, daß ich gar keine Warnung wie "condition is always true" mehr erzeugen kann.
-
volkard schrieb:
Bashar schrieb:
Glaub ich nicht. Der Grund ist, dass man bei do-while am Ende zwingend ein Semikolon braucht.
#include <stdio.h> void Usart(char ch){ } #define uart_put_string1(data_string) do { \ char const *uart_put_string_intern_p = data_string; \ while(*uart_put_string_intern_p) Usart(*uart_put_string_intern_p++); \ } while(0) #define uart_put_string2(data_string) if(1) { \ char const *uart_put_string_intern_p = data_string; \ while(*uart_put_string_intern_p) Usart(*uart_put_string_intern_p++); \ } else ((void)0) int main(void) { if(1) { uart_put_string1("hallo"), printf("test"); // Compilerfehler uart_put_string2("hallo"), printf("test"); // compiliert, macht aber komische Sachen } return 0; }