#MAKROS zusammenfassen

#4085376
Lesenswert?
• ▲
▼
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.
Gast #4085396
Lesenswert?
• ▲
▼
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);}
}
#4085431
Lesenswert?
• ▲
▼
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 wird
1
  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.
#4085447
Lesenswert?
• ▲
▼
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.
Gast #4085465
Lesenswert?
• ▲
▼
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!

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.