Ja kann man. Diese trennt man mit einem Semikolon. Am besten fasst du
die Anweisungen in einer do-while Schleife zusammen, da sich diese wie
eine einzige Anweisung verhält:
1
#define a1 do{PORTB |= (1 <<PB1); PORTA |= (1 <<PA0);}while(0)
be stucki schrieb:> Ja kann man. Diese trennt man mit einem Semikolon. Am besten fasst du> die Anweisungen in einer do-while Schleife zusammen, da sich diese wie> eine einzige Anweisung verhält:>
1
#define a1 do{PORTB |= (1 <<PB1); PORTA |= (1 <<PA0);}while(0)
Thomas Eckmann schrieb:> Und wenn es ein bisschen umfangreicher wird:
Hierbei wichtig: Hinter den \ darf kein weiteres Zeichen stehen, auch
kein Whitespace (Leerzeichen, Tabs).
Keinerlei Performance/Platz-Nachteil ggü. dem #define, vermeidet
> aber all die potentiellen Probleme von Makros und die Frickelei mit> do-while etc.
Wenn der Compiler das kann und will, macht er das auch.
In diesem einfachen Beispiel vielleicht sogar von sich aus ohne
inline-Deklaration. Aber ein paar Konjunktive gibt es dabei.
mfg.
Amateur schrieb:> Wird das Schleifenkonstrukt (do-while) wirklich rückstandslos entfernt,> oder behalte ich eine "unsichtbare" Sprung- bzw. Abfrageanweisung> zurück?
Nein das schmeisst der Compiler vollkommen raus. Ist ja auch vollkommen
sinnlos.
Eigentlich gehört das auch so
#define a1() do{PORTB |= (1 <<PB1); PORTA |= (1 <<PA0);}while(0)
Damit kannst/musst du das Makro wie eine Funktion aufrufen a1();
Und fliegst ohne die do... while in einer if-Abfrage voll auf die
Fresse.
if(bla) a1(); else a2();
Das jetzt mal für den TO, der sich wahrscheinlich fragt, was das soll.
mfg.
Thomas Eckmann schrieb:> Wenn der Compiler das kann und will, macht er das auch.> In diesem einfachen Beispiel vielleicht sogar von sich aus ohne> inline-Deklaration. Aber ein paar Konjunktive gibt es dabei.
Wenn du so paranoid bist schreibst du "__attribute__((always_inline))
inline" dran (nur GCC & Clang), dann wird es garantiert ge-inlined und
ist somit garantiert so effizient wie das Makro, provoziert nur viel
weniger Probleme.
Thomas Eckmann schrieb:> Damit kannst/musst du das Makro wie eine Funktion aufrufen a1();> Und fliegst ohne die do... while in einer if-Abfrage voll auf die> Fresse.
Warum ein Makro schreiben das wie eine Funktion verwendbar ist, wenn
man auch einfach eine Funktion schreiben kann?
Max H. schrieb:> Wieso sollte es das nicht sein?
Weil der Name blöd ist, da weiß keiner was gemeint ist. Was wird denn da
eingeschaltet, PWM, UART, LED, USB?
Dr. Sommer schrieb:> Thomas Eckmann schrieb:>> Wenn der Compiler das kann und will, macht er das auch.>> In diesem einfachen Beispiel vielleicht sogar von sich aus ohne>> inline-Deklaration. Aber ein paar Konjunktive gibt es dabei.> Wenn du so paranoid bist schreibst du "__attribute__((always_inline))> inline" dran (nur GCC & Clang), dann wird es garantiert ge-inlined und> ist somit garantiert so effizient wie das Makro, provoziert nur viel> weniger Probleme.
Ich bin nicht paranoid, du A...
> Thomas Eckmann schrieb:>> Damit kannst/musst du das Makro wie eine Funktion aufrufen a1();>> Und fliegst ohne die do... while in einer if-Abfrage voll auf die>> Fresse.> Warum ein Makro schreiben das wie eine Funktion verwendbar ist, wenn> man auch einfach eine Funktion schreiben kann?
Hab ich schon geschrieben.
mfg.
Max H. schrieb:> Max H. schrieb:>> Für meine LCD Routine [...]
Das muss man dann aber immer manuell dazuschreiben. EnableLCD wäre doch
wesentlich deskriptiver gewesen.
Auch wenn euch das Beispiel nicht passt, mehrere Aweisungen hinter einem
#define sind also problemlos ohne das do while möglich...
Und um das zu zeigen ist der Namen des defines irrelevant...
Max H. schrieb:> Auch wenn euch das Beispiel nicht passt, mehrere Aweisungen hinter> einem> #define sind also problemlos ohne das do while möglich...> Und um das zu zeigen ist der Namen des defines irrelevant...
Und was passiert dann?
Und was wird dadraus? (Einrückung zur Verdeutlichung dessen was
passiert)
1
intmain(){
2
if(bedingung)
3
Delay10TCYx(1);
4
LCD_EN=1;
5
Delay10TCYx(1);
6
LCD_EN=0;
7
Delay10TCYx(1)
8
}
Die Initialisierung erfolgt also immer halb oder ganz, aber nie gar
nicht. Ob das beansichtigt war?
Noch hässlicher wirds dann wenn man temporäre Variablen und Paramenter
benötigt...
Um sowas muss man sich keine Gedanken machen wenn man einfach eine
Funktion verwendet.
Max H. schrieb:> Auch wenn euch das Beispiel nicht passt, mehrere Aweisungen hinter einem> #define sind also problemlos ohne das do while möglich...> Und um das zu zeigen ist der Namen des defines irrelevant...
Weil du Glück hast und das Makro nur auf eine Art und Weise benutzt. Es
ist dein Makro und nur in deinen Programmen von dir verwendbar.
1
intmain(void)
2
{
3
Enable;
4
Init();
5
....
6
}
funktioniert.
In diesem speziellen Fall nicht relevant, aber:
1
if(bla)Enable;else(//was weiss ich);
dann steht da plötzlich:
1
if(bla)Delay10TCYx(1);
2
LCD_EN=1;
3
Delay10TCYx(1);
4
LCD_EN=0;
5
Delay10TCYx(1);
6
else(//was...)
Das Delay wird nur ausgeführt wenn bla true ist, der Rest immer.
Und das else steht ohne if völlig alleine da.
Deswegen gehört die do...while()-Schleife da herum.
Der Name ist trotzdem nicht aussagekräftig.
Makros sind oft Scheisse. Es sei denn, man macht es richtg. Und dann
kann man noch Stunden darüber diskutieren, ob man die überhaupt
verwenden soll. Die do...while -Krücke ist für viele ein Argument davon
abzuraten.
Entweder man benutzt diese Krücke oder man benutzt keine Makros mit
mehreren Anweisungen. Mit deinem Makro schiesst du dir nur selbst ins
Knie.
Mit diesem speziellen wahrscheinlich nicht. Aber wenn du deine Makros
immer so schreibst, mit Sicherheit irgendwann. Und wenn die if-Bedingung
dann ohne else dasteht, gibt es nicht einmal eine Fehlermeldung.
mfg.
Finde inline Funktionen auch am Schönsten.
Allerdings nur mit Attribut "always inline".
Ich hab mal recht viel mit inline experimentiert und bin zu dem Ergebnis
gekommen:
Eine Funktion nur als "inline" zu definieren bringt garnichts.
Mit eingeschalteter Optimierung wird der gcc sie sowieso inlinen, wenn
er der Meinung ist es bringt was.
Und andersherum wird er sie nicht inlinen wenn der Code deswegen zu groß
wird (z.B. bei mehreren Aufrufen), trotz "inline".
Kann das jemand so bestätigen?
Haro schrieb:> Und andersherum wird er sie nicht inlinen wenn der Code deswegen zu groß> wird (z.B. bei mehreren Aufrufen), trotz "inline".>> Kann das jemand so bestätigen
Leider ja. Es ist sogar noch schlimmer: Selbst wenn der Code durch
(sogar mehrfach auftretendes) inlinen kleiner würde (durch optimieren
der Operation und wegfallen des Aufrufs&Parameter-Übergabe -Overhead)
macht der GCC das nicht immer. Daher muss man sich mit
__attribute__((always_inline)) behelfen. In C++11 ist sogar eine
Standard-Notation dafür vorgesehen (um Compiler-unabhängig zu sein) aber
die unterstützt GCC noch nicht :-/ Aber alles besser als ein Makro,
insbesondere eines für das es 0 Grund gibt, ein Makro zu sein (wie
Code-Generierung, impliziter Zugriff auf lokale Variablen (hässlich)
etc.)