Makro

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche

Makros sind eine mehr oder weniger große Anzahl von Anweisungen, die unter einer Kurzbezeichnung zu einer Gruppe zusammengefasst sind und als Einheit verwendbar sind. Makros werden i.d.R von Assemblersprachen angeboten, sind aber auch in einigen höheren Programmiersprachen verfügbar etwa in C/C++ durch den C-Präprozessor. Schließlich gibt es auch reine Makrosprachen (etwa den Makroprozessor m4 von Unix/Linux), die als Werkzeug zur systematischen Transformation von Textdateien eingesetzt werden können.

Hinsichtlich eines Makros ist zu unterscheiden zwischen dessen Definition, i.d.R. einmalig und VOR der ersten Verwendung (evtl. auch in Include-Files) und dessen Verwendungen (0-mal bis beliebig oft).

Allgemeines zu Makros

Besonders flexibel sind parametrisierbare Makros. Die Makro-Definition ist dann als eine Schablone zu sehen, bei der einige Stellen noch offen gehalten wurden, um sie erst später, bei der Makro-Verwendung zu füllen. Bei der Programmierung haben parametrisierbare Makros eine gewisse Ähnlichkeit zu Unterprogrammen (mit Parametern), werden aber anders als diese zum Zeitpunkt der Übersetzung ausgeführt und hinsichtlich der Parameterwerte festgelegt.

Bei der Programmierung von Mikrocontrollern ist es mitunter erforderlich, zwischen der Verwendung von Unterprogrammen und Makros abzuwägen. Universell wiederverwendbare, und deshalb in einer gewissen Umfang noch konfigurierbare Programmteile können in Form von Makros effizienter als Unterprogramme sein. Allerdings müssen die folgenden Voraussetzungen bestehen:

  1. Der "variable" Teil (= aktuelle Werte der Parameter) muss bei der Kompilierung festgelegt werden können. Sofern dieser Punkt nicht sichergestellt ist, scheiden (parametrisierte) Makros komplett aus.
  2. Der Makro wird nur ein einziges Mal in genau dieser Form verwendet. Ob die Mehrfachverwendung eines Makros mit identischen Parametern ein Vor- oder Nachteil gegenüber einem Unterprogramm ist, hängt davon ab, was optimiert werden soll. Im Hinblick auf die Ausführungsgeschwindigkeit ist der Makro vorteilhaft, geht es um geringe Code-Größe ist fast immer das Unterprogramm besser. Die Ausnahme von dieser Regel bilden triviale Makros, die weniger Maschinen-Code erzeugen als der Befehl für einen Unterprogrammsprung und die notwendige Parameterübergabe.

Makros vs. Inline-Funktionen

Anstatt ein Makro zu verwenden, kann eine Funktion auch mit dem Schlüsselwort "inline" versehen werden. Dies ist ein Hinweis für den Compiler, dass er den Code der Inline-Funktion direkt an dieser Stelle einfügen soll, an der die Funktion aufgerufen wird. Ob der Compiler diesem Hinweis folgt, ist seine Entscheidung[1][2].

Vorteile von Inline Funktionen

Typensicherheit
Der Compiler kann die Typen der Parameter prüfen und Fehler erkennen. Einem Makro kann eigentlich alles übergeben werden, was dann zu seltsamen Fehlermeldungen beim compilieren oder schlimmer einem seltsamen Programmverhalten führen. Beispiels sind im Artikel C-Präprozessor zu finden.
Parameterauswertung
Die Parameter werden ausgewertet, bevor die Inline-Funktion aufgerufen wird. Insbesondere, wenn die Parameterauswertung Nebeneffekte wie Post-Increment hat oder ein Parameter mehrfach verwendet wird, helfen Inline-Funktionen, unangenehme Überaschungen zu vermeiden. Auch hier sei wieder für Beispiele auf den Artikel C-Präprozessor verwiesen.
Makros sind nur Hacks
Makros sollten vermieden werden, da sie das Debuggen erschweren und sie der strukturierten Programmierung widersprechen. Insbesondere komplexe, vermeintlich geniale und verschachtelte Makros können für andere oder für einen selber nach einiger Zeit schon komplett unverständlich sein.

Vorteile von Makros

Textersetzung
Makros sind etwas flexibler, da in ihnen bestimme Code-Schnipsel, die oft vorkommen, zusammengefasst werden können. Erst nach dem Einbauen des Makros durch den Preprozessor muss sich gültiger C-Code ergeben. Dadurch können Makros an manchen Stellen sehr flexibel eingesetzt werden.
Makros sind genial
Mit Makros kann man einige Sachen kompakt darstellen und inbesondere lästige Code-Wiederholungen vermeiden bzw. an eine Stelle zentral warten.

Also jetzt Makros oder Inline-Funktionen?

Es ist wohl zum Teil eine Glaubenfrage über die sich lange vortrefflich streiten lässt. Die einen sagen, dass eben schon immer Makros verwendet wurden und sie zu C einfach dazu gehören (und zu Assembler sowieso). Die anderen sehen sie eher als Altlast aus Zeiten an, in der Code in Assember geschrieben wurde, die Compiler schlecht waren und ein Goto nichts böses war....

Die Erfahrung bei grösseren Projekten (vor allem im Nicht-uC oder 32-bit uC-Bereich) zeigt aber, dass der Einsatz von Makro mit Bedacht erfolgen sollte. Je abstrakter das Modul wird, desto weniger Makros sollten verwendet werden. Trotzdem sind Makros gerade dann sinnvoll, wenn man direkt an der Hardware programmiert und weit weg von strukturiert objektorientierter Programmierung ist. Um den einen oder anderen von Hand optimierten Hack kommt man dann einfach nicht herum, weil die der Compiler das sonst einfach doch nicht schafft.

Trotzdem sei an dieser Stelle gewarnt, sich in vermeintlich tollen Makro zu verrennen, ohne über das ganze mal eine Nacht zu überschlafen. Jede vermeintliche Optimierung über Makro-Hacks sollte am Ende auch wirklich eine Optimierung sein.

An dieser Stelle erwartet der Autor hitzige Debatten und praktische Beispiele darüber, was Compiler einfach nicht hinbekommen... :)

Fußnoten

Siehe auch