Hallo, wie kann Makros zusammenfassen
dass es bei der unteren Abfrage nicht zu Problemen kommt, wegen
fehlenden { } bzw. gesetzter { }
#define MAKRO1(x) setBit(x); sendBit(1);
if(i == 1) MAKRO(4); else MAKRO(5);
else if(i == 2) { do(); di(); MAKRO(0);}
else {MARKO(5);}
mit geschweiften klammern werden Blöcke zusammengefast
das geht auch wenn da kein if, for, while, ect steht.
Daher:
#define MAKRO1(x) {setBit(x); sendBit(1);}
Danke ;) Hätte jetzt nicht gedacht, dass es auch ohn vorstehender Anweisung möglich ist.
Eigentlich geht es um etwas ganz anderes. Dir scheint nicht klar zu sein, dass ein Makro im Wesentlichen einfach nur ein Textersatz ist. Ein Text wird durch einen anderen Text ersetzt. Mit 'Makro zusammenfassen' hat das nichts zu tun. Du musst nur wissen, welchen (langen) Text durch einen kürzeren Makronamen ersetzt haben willst. Wenn du also diesen C Code als Ziel hast
1 | while( hamstibamsti ) |
2 | {
|
3 | mach was; mach noch was; |
4 | }
|
und du willst den Teil
1 | {
|
2 | mach was; mach noch was; |
3 | }
|
durch ein Makro namens 'SEPP' ersetzen, dann brauchst du also im Prinzip eine Textersetzung, die dir aus 'SEPP' genau den gewünschten Zieltext erzeugt.
1 | {
|
2 | SEPP --------> mach was; mach noch was; |
3 | } |
ergo schreibst du dein Makro
1 | #define SEPP { \
|
2 | mach was; mach noch was; \
|
3 | }
|
und verwendest es
1 | while( hamstibamsti ) |
2 | SEPP
|
Wenn du in Gedanken die Textersetzung machst, kommt genau der gewünschte Zieltext raus. Bei Makros fängt man daher meistens 'hinten' an, in dem man sich überlegt, welcher Zieltext eigentlich rauskommen soll. Dann überlegt man sich, wie man diesen Zieltext in einer 'einfacheren' Schreibweise haben möchte und schreibt sich das Makro welches bei Textersetzung aus der einfacheren Form wieder den ursprüngliche Zieltext ergibt. hinter einem #define steckt nichts geheimnisvolles. Das ist im Grunde einfch nur eine Regel wie ein Text durch einen anderen Text ersetzt werden soll, wobei auch noch Argumente erlaubt sind, die in den Zieltext eingebaut werden. Aber recht viel mehr steckt da nicht dahinter.
Vielleicht etwas umständlich und ungenau ausgedrückt
ich habe eine Entscheidungsfall, wie etwas ausgeführt werden soll
#define DEBUG 1
#if DEBUG
#define SETOUT(x) printf("%i\n", x)
#else
#define SETOUT(x) { test |= 1<<x; send(test) }
#endif
Fall 1:
int main(void)
{
if(i) SETOUT(1);
else SETOUT(0);
}
Fall 2:
int main(void)
{
if(i) { SETOUT(1); nochwasanderes(); }
else {SETOUT(0);}
}
Laie schrieb: > #define SETOUT(x) { test |= 1<<x; send(test) } > > if(i) SETOUT(1); > else SETOUT(0); Das wird allerdings so nicht funktionieren. (Selbst dann nicht, wenn ich den fehlenden ; im Block ergänze) Warum nicht? Sehen wir uns das Ersetzungsergebnis an:
1 | if(i) { test |= 1<<1; send(test); }; |
2 | else { test |= 1<<0; send(test); }; |
und jetzt formatieren wir etwas um, wobei wir im Hinterkopf halten, dass
ein {-} Block nicht durch einen ; abgeschlossen wird1 | if(i) |
2 | {
|
3 | test |= 1<<1; send(test); |
4 | }
|
5 | ;
|
6 | else
|
7 | {
|
8 | test |= 1<<0; send(test); |
9 | }
|
10 | ;
|
Das Problem ist der ; hier
1 | if(i) |
2 | {
|
3 | test |= 1<<1; send(test); |
4 | }
|
5 | ; <------ |
syntaktisch gehört er nicht zum Block sondern bildet seine eigene, leere Anweisung. Mit dieser eigenständigen Anweisung ist aber das vorhergehende if abgeschlossen. Das nachfolgende else gehört nicht mehr zu diesem if. Das Ergebnis ist ein Syntax Fehler. Was war das Programmierer-Problem? Der Programmierer hat, so wie er es gewohnt ist, hier
1 | if(i) SETOUT(1); |
ganz automatisch einen ; gesetzt. So wie er es gewohnt ist, wenn da eine Anweisung oder ein Funktionsaufruf steht. Nur ist hier dieser ; kontraproduktiv, wie man erkennen kann, wenn man die Makrosubstitution macht. Man könnte jetzt natürlich den ; weglassen
1 | if(i) SETOUT(1) |
2 | else SETOUT(0) |
aber das 1) sieht seltsam aus 2) funktioniert wiederrum nur dann, wenn man in der Makroersetzung einen Block hat. Was man also brauchen würde, das ist ein Text in der Makroersetzung, der a) als Block fungiert b) das nachfolgende ; aus dem Quelltext wegkonsumiert. Und an dieser Stelle taucht dann die Makroversion
1 | #define SETOUT(x) do { test |= 1<<x; send(test); } while(0)
|
auf, die genau das gewünschte leistet. Sie führt einen Block ein, so dass man mehrere Anweisungen kapseln kann, ist aber auf der anderen Seite so geschrieben, dass der ; aus dem Quelltext
1 | if(i) SETOUT(1); |
2 | else SETOUT(0); |
einen syntaktischen Zusammenhang mit dem Block kriegt. Nach Textersetzung (und lesbarer Formatierung) ergibt sich
1 | if(i) |
2 | do { |
3 | test |= 1<<1; send(test); |
4 | } while(0) ; |
5 | |
6 | else
|
7 | do { |
8 | test |= 1<<0; send(test); |
9 | } while(0) ; |
und hier sieht man schon, dass alles in Ordnung ist. Der fragliche ; gehört jetzt zur do-while Loop, ist kein leeres Statement, beendet daher nicht das if und damit hängt auch nicht das else in der Luft.
Laie schrieb: > Fall 1: > int main(void) > { > if(i) SETOUT(1); > else SETOUT(0); > } Geschweifte Klammern hier nicht weglassen, siehe Beitrag von Karl Heinz
1 | int main(void) { |
2 | if(i) { |
3 | SETOUT(1); |
4 | } else { |
5 | SETOUT(0); |
6 | }
|
7 | }
|
das daraus dann:
1 | int main(void) { |
2 | if(i) { |
3 | { test |= 1<<1; send(test) }; |
4 | } else { |
5 | { test |= 1<<0; send(test) }; |
6 | }
|
7 | }
|
wird ist kein Problem.
Hallo Christian, das mit dem Klammern ist mir an der Stelle bewusst, deshalb habe ich auch beide möglichen Fälle gepostet. Viele einzelne Anweisungen sind zum schreiben nicht so prickelnd durchenden mit den geschweiften Klammern. Die 2. Lösung mit der do while ist genau das richtige! Danke!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.