Überlegen Sie sich zur Beantwortung Ihrer Fragen, wofür Makros überwiegend verwendet werden (Warnung: Gehirn-kompilierter Code).
- Makros zum Definieren symbolischer Konstanten
#define X 100
Dies kann leicht ersetzt werden durch: const int X = 100;
- Makros, mit denen (im Wesentlichen) typunabhängige Inline-Funktionen definiert werden
#define max(X,Y) (X>Y?X:Y)
In jeder Sprache, die das Überladen von Funktionen unterstützt, kann dies durch Überladen von Funktionen des richtigen Typs oder in einer Sprache, die Generika unterstützt, durch eine generische Funktion wesentlich typsicherer emuliert werden. Das Makro wird gerne versuchen, alles zu vergleichen , einschließlich Zeiger oder Zeichenfolgen, die möglicherweise kompiliert werden, aber mit ziemlicher Sicherheit nicht das sind, was Sie wollten. Auf der anderen Seite bieten Makros, die Sie typsicher gemacht haben, keine Vorteile oder Bequemlichkeiten gegenüber überladenen Funktionen.
- Makros, mit denen Verknüpfungen zu häufig verwendeten Elementen angegeben werden.
#define p printf
Dies kann leicht durch eine Funktion ersetzt werden p()
, die dasselbe tut. Dies ist mit C verbunden (Sie müssen die va_arg()
Funktionsfamilie verwenden), in vielen anderen Sprachen, die eine variable Anzahl von Funktionsargumenten unterstützen, ist dies jedoch viel einfacher.
Die Unterstützung dieser Funktionen in einer Sprache anstelle einer speziellen Makrosprache ist einfacher, weniger fehleranfällig und für andere, die den Code lesen, weitaus weniger verwirrend. Tatsächlich fällt mir kein einziger Anwendungsfall für Makros ein, der nicht einfach auf andere Weise dupliziert werden kann. Der einzige Ort, an dem Makros wirklich nützlich sind, ist, wenn sie an bedingte Kompilierungskonstrukte wie #if
(usw.) gebunden sind .
In diesem Punkt werde ich nicht mit Ihnen streiten, da ich glaube, dass Nicht-Präprozessor-Lösungen für die bedingte Kompilierung in gängigen Sprachen äußerst umständlich sind (wie die Bytecode-Injektion in Java). Sprachen wie D haben jedoch Lösungen entwickelt, die keinen Präprozessor erfordern und nicht umständlicher sind als die Verwendung von Präprozessor-Bedingungen, während sie weitaus weniger fehleranfällig sind.