Forum: Mikrocontroller und Digitale Elektronik #MAKROS zusammenfassen


von Laie (Gast)


Lesenswert?

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);}

von Christian K. (the_kirsch)


Lesenswert?

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);}

von PittyJ (Gast)


Lesenswert?

#define MAKRO1(x)    {setBit(x); sendBit(1);}

von Laie (Gast)


Lesenswert?

Danke ;)

Hätte jetzt nicht gedacht, dass es auch ohn vorstehender Anweisung 
möglich ist.

von Karl H. (kbuchegg)


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.

von Laie (Gast)


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);}
}

von Karl H. (kbuchegg)


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.

von Christian K. (the_kirsch)


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.

von Laie (Gast)


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!

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
Noch kein Account? Hier anmelden.