Namensräume
Varianten
Aktionen

Textmakroersetzung

Von cppreference.com

Der Präprozessor unterstützt Textmakroersetzung und funktionsähnliche Textmakroersetzung.

Inhalt

[bearbeiten] Syntax

#define Bezeichner Ersetzungsliste (optional) (1)
#define Bezeichner ( Parameter ) Ersetzungsliste (2)
#define Bezeichner ( Parameter, ... ) Ersetzungsliste (3) (seit C99)
#define Bezeichner ( ... ) Ersetzungsliste (4) (seit C99)
#undef Bezeichner (5)

[bearbeiten] Erklärung

[bearbeiten] #define Direktiven

Die #define Direktiven definieren den Bezeichner als Makro, d.h. sie weisen den Compiler an, alle nachfolgenden Vorkommen von Bezeichner durch Ersetzungsliste zu ersetzen, welche optional zusätzlich verarbeitet werden kann. Wenn der Bezeichner bereits als Makro eines beliebigen Typs definiert ist, ist das Programm schlecht geformt, es sei denn, die Definitionen sind identisch.

[bearbeiten] Objektähnliche Makros

Objektähnliche Makros ersetzen jedes Vorkommen eines definierten Bezeichners durch Ersetzungsliste. Version (1) der #define Direktive verhält sich genau so.

[bearbeiten] Funktionsähnliche Makros

Funktionsähnliche Makros ersetzen jedes Vorkommen eines definierten Bezeichners durch Ersetzungsliste, wobei zusätzlich eine Anzahl von Argumenten genommen wird, die dann entsprechende Vorkommen eines beliebigen der Parameter in der Ersetzungsliste ersetzen.

Die Syntax einer funktionsähnlichen Makroaufrufung ist ähnlich der Syntax eines Funktionsaufrufs: Jede Instanz des Makronamens, gefolgt von einem ( als nächstem Präprozessor-Token, leitet die Folge von Tokens ein, die durch die Ersetzungsliste ersetzt wird. Die Folge wird durch das passende ) Token beendet, wobei dazwischen liegende, übereinstimmende Paare von linken und rechten Klammern übersprungen werden.

Die Anzahl der Argumente muss gleich der Anzahl der Argumente in der Makrodefinition (Parameter) sein oder das Programm ist schlecht geformt. Wenn der Bezeichner nicht in funktionaler Notation steht, d.h. keine Klammern nach sich hat, wird er gar nicht ersetzt.

Version (2) der #define Direktive definiert ein einfaches funktionsähnliches Makro.

Version (3) der #define Direktive definiert ein funktionsähnliches Makro mit variabler Anzahl von Argumenten. Die zusätzlichen Argumente können über den Bezeichner __VA_ARGS__ zugegriffen werden, der dann mit den Argumenten ersetzt wird, die dem zu ersetzenden Bezeichner zugeordnet sind.

Version (4) der #define Direktive definiert ein funktionsähnliches Makro mit variabler Anzahl von Argumenten, aber ohne reguläre Argumente. Auf die Argumente kann nur über den Bezeichner __VA_ARGS__ zugegriffen werden, der dann mit den Argumenten ersetzt wird, die dem zu ersetzenden Bezeichner zugeordnet sind.

Für die Versionen (3,4) kann die Ersetzungsliste die Tokenfolge __VA_OPT__ ( Inhalt ) enthalten, die durch Inhalt ersetzt wird, wenn __VA_ARGS__ nicht leer ist, und ansonsten zu nichts expandiert.

#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)
F(a, b, c) // replaced by f(0, a, b, c)
F()        // replaced by f(0)
 
#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__)
G(a, b, c) // replaced by f(0, a, b, c)
G(a, )     // replaced by f(0, a)
G(a)       // replaced by f(0, a)
 
#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ })
SDEF(foo);       // replaced by S foo;
SDEF(bar, 1, 2); // replaced by S bar = { 1, 2 };
(seit C23)


Hinweis: Wenn ein Argument eines funktionsähnlichen Makros Kommas enthält, die nicht durch übereinstimmende Paare von linken und rechten Klammern geschützt sind (wie z.B. makro(array[x = y, x + 1]) oder atomic_store (p, (struct S){ a, b });), wird das Komma als Trennzeichen für Makroargumente interpretiert, was aufgrund von Argumentanzahl-Fehlern zu einem Kompilierungsfehler führt.

[bearbeiten] # und ## Operatoren

In funktionsähnlichen Makros nimmt ein # Operator vor einem Bezeichner in der Ersetzungsliste den Bezeichner durch Parameterersetzung und schließt das Ergebnis in Anführungszeichen ein, wodurch effektiv ein String-Literal erstellt wird. Zusätzlich fügt der Präprozessor Backslashes hinzu, um die Anführungszeichen um eingebettete String-Literale, falls vorhanden, zu maskieren, und verdoppelt die Backslashes im String bei Bedarf. Alle führenden und nachfolgenden Leerzeichen werden entfernt, und jede Folge von Leerzeichen in der Mitte des Textes (aber nicht innerhalb von eingebetteten String-Literal-Zeichenfolgen) wird zu einem einzigen Leerzeichen zusammengefasst. Diese Operation wird als "Stringifizierung" bezeichnet. Wenn das Ergebnis der Stringifizierung kein gültiges String-Literal ist, ist das Verhalten undefiniert.

Wenn # vor __VA_ARGS__ erscheint, wird der gesamte expandierte __VA_ARGS__ in Anführungszeichen eingeschlossen.

#define showlist(...) puts(#__VA_ARGS__)
showlist();            // expands to puts("")
showlist(1, "x", int); // expands to puts("1, \"x\", int")
(seit C99)

Ein ## Operator zwischen zwei aufeinanderfolgenden Bezeichnern in der Ersetzungsliste führt eine Parameterersetzung für die beiden Bezeichner durch und verkettet dann das Ergebnis. Diese Operation wird als "Konkatenation" oder "Token-Pasting" bezeichnet. Nur Tokens, die zusammen ein gültiges Token bilden, können zusammengefügt werden: Bezeichner, die einen längeren Bezeichner bilden, Ziffern, die eine Zahl bilden, oder Operatoren + und =, die ein += bilden. Ein Kommentar kann nicht durch das Zusammenfügen von / und * erstellt werden, da Kommentare aus dem Text entfernt werden, bevor die Makrosubstitution betrachtet wird. Wenn das Ergebnis der Konkatenation kein gültiges Token ist, ist das Verhalten undefiniert.

Hinweis: Einige Compiler bieten eine Erweiterung, die es erlaubt, dass ## nach einem Komma und vor __VA_ARGS__ erscheint. In diesem Fall bewirkt ## nichts, wenn __VA_ARGS__ nicht leer ist, entfernt aber das Komma, wenn __VA_ARGS__ leer ist: Dies ermöglicht die Definition von Makros wie fprintf (stderr, format, ##__VA_ARGS__).

Die Auswertungsreihenfolge von # und ## Operatoren ist nicht spezifiziert.

[bearbeiten] #undef Direktive

Die #undef Direktive hebt die Definition des Bezeichners auf, d.h. sie bricht die vorherige Definition des Bezeichners durch eine #define Direktive ab. Wenn der Bezeichner kein zugeordnetes Makro hat, wird die Direktive ignoriert.

[bearbeiten] Vordefinierte Makros

Die folgenden Makronamen sind in jeder Translation Unit vordefiniert

__STDC__
expandiert zur ganzzahligen Konstante 1. Dieses Makro soll eine konforme Implementierung anzeigen
(Makro-Konstante)
__STDC_VERSION__
(C95)
expandiert zu einer ganzzahligen Konstante vom Typ long, deren Wert mit jeder Version des C-Standards steigt
  • 199409L (C95)
  • 199901L (C99)
  • 201112L (C11)
  • 201710L (C17)
  • 202311L (C23)
    (Makro-Konstante)
__STDC_HOSTED__
(C99)
expandiert zur ganzzahligen Konstante 1, wenn die Implementierung gehostet ist (läuft unter einem Betriebssystem), 0 wenn sie eigenständig ist (läuft ohne Betriebssystem)
(Makro-Konstante)
__FILE__
expandiert zum Namen der aktuellen Datei als Zeichenketten-Literal, kann durch die #line Direktive geändert werden
(Makro-Konstante)
__LINE__
expandiert zur Quellcodedatei-Zeilennummer, einer ganzzahligen Konstante, kann durch die #line Direktive geändert werden
(Makro-Konstante)
__DATE__
expandiert zum Übersetzungsdatum, einem Zeichenketten-Literal im Format "Mmm dd yyyy". Der Monatsname ist so, als ob er von asctime generiert wurde, und das erste Zeichen von "dd" ist ein Leerzeichen, wenn der Tag des Monats kleiner als 10 ist.
(Makro-Konstante)
__TIME__
expandiert zur Übersetzungszeit, einem Zeichenketten-Literal im Format "hh:mm:ss", wie in der von asctime() generierten Zeit.
(Makro-Konstante)
__STDC_UTF_16__
(C23)
expandiert zu 1, um anzuzeigen, dass char16_t UTF-16-Kodierung verwendet.
(Makro-Konstante)
__STDC_UTF_32__
(C23)
expandiert zu 1, um anzuzeigen, dass char32_t UTF-32-Kodierung verwendet.
(Makro-Konstante)
__STDC_EMBED_NOT_FOUND____STDC_EMBED_FOUND____STDC_EMBED_EMPTY__
(C23)
expandieren zu 0, 1 bzw. 2
(Makro-Konstante)

Die folgenden zusätzlichen Makronamen können von einer Implementierung vordefiniert werden

__STDC_ISO_10646__
(C99)
expandiert zu einer ganzzahligen Konstante im Format yyyymmL, wenn wchar_t Unicode verwendet; das Datum gibt die neueste unterstützte Unicode-Revision an.
(Makro-Konstante)
__STDC_IEC_559__
(C99)
expandiert zu 1, wenn IEC 60559 unterstützt wird (veraltet)(seit C23)
(Makro-Konstante)
__STDC_IEC_559_COMPLEX__
(C99)
expandiert zu 1, wenn IEC 60559 komplexe Arithmetik unterstützt wird (veraltet)(seit C23)
(Makro-Konstante)
__STDC_UTF_16__
(C11)
expandiert zu 1, wenn char16_t UTF-16-Kodierung verwendet.
(Makro-Konstante)
__STDC_UTF_32__
(C11)
expandiert zu 1, wenn char32_t UTF-32-Kodierung verwendet.
(Makro-Konstante)
__STDC_MB_MIGHT_NEQ_WC__
(C99)
expandiert zu 1, wenn 'x' = L'x' für ein Element des grundlegenden Zeichensatzes falsch sein könnte, z. B. auf EBCDIC-basierten Systemen, die Unicode für wchar_t verwenden.
(Makro-Konstante)
__STDC_ANALYZABLE__
(C11)
expandiert zu 1, wenn Analysierbarkeit unterstützt wird.
(Makro-Konstante)
__STDC_LIB_EXT1__
(C11)
expandiert zu einer ganzzahligen Konstante 201112L, wenn Grenzwertprüfende Schnittstellen unterstützt werden.
(Makro-Konstante)
__STDC_NO_ATOMICS__
(C11)
expandiert zu 1, wenn atomare Typen und die atomare Operationen-Bibliothek nicht unterstützt werden.
(Makro-Konstante)
__STDC_NO_COMPLEX__
(C11)
expandiert zu 1, wenn komplexe Typen und die komplexe Mathematik-Bibliothek nicht unterstützt werden.
(Makro-Konstante)
__STDC_NO_THREADS__
(C11)
expandiert zu 1, wenn Multithreading nicht unterstützt wird.
(Makro-Konstante)
__STDC_NO_VLA__
(C11)
expandiert zu 1, wenn arrays variabler Länge und variabel modifizierte Typen(bis C23)mit automatischer Speicherzuweisung(seit C23) nicht unterstützt werden.
(Makro-Konstante)
__STDC_IEC_60559_BFP__
(C23)
expandiert zu 202311L, wenn IEC 60559 binäre Gleitkommaarithmetik unterstützt wird.
(Makro-Konstante)
__STDC_IEC_60559_DFP__
(C23)
expandiert zu 202311L, wenn IEC 60559 Dezimalgleitkommaarithmetik unterstützt wird.
(Makro-Konstante)
__STDC_IEC_60559_COMPLEX__
(C23)
expandiert zu 202311L, wenn IEC 60559 komplexe Arithmetik unterstützt wird.
(Makro-Konstante)
__STDC_IEC_60559_TYPES__
(C23)
expandiert zu 202311L, wenn IEC 60559 Austausch- und erweiterte Typen unterstützt werden.
(Makro-Konstante)

Die Werte dieser Makros (außer __FILE__ und __LINE__) bleiben während der gesamten Translation Unit konstant. Versuche, diese Makros neu zu definieren oder ihre Definition aufzuheben, führen zu undefiniertem Verhalten.

Die vordefinierte Variable __func__ (siehe Funktionsdefinition für Details) ist kein Präprozessor-Makro, auch wenn sie manchmal zusammen mit __FILE__ und __LINE__ verwendet wird, z.B. von assert.

(seit C99)

[bearbeiten] Beispiel

#include <stdio.h>
 
// make function factory and use it
#define FUNCTION(name, a) int fun_##name(int x) { return (a) * x; }
 
FUNCTION(quadruple, 4)
FUNCTION(double, 2)
 
#undef FUNCTION
#define FUNCTION 34
#define OUTPUT(a) puts( #a )
 
int main(void)
{
    printf("quadruple(13): %d\n", fun_quadruple(13) );
    printf("double(21): %d\n", fun_double(21) );
    printf("%d\n", FUNCTION);
    OUTPUT(billion);               // note the lack of quotes
}

Ausgabe

quadruple(13): 52
double(21): 42
34
billion

[bearbeiten] Fehlerberichte

Die folgenden verhaltensändernden Defect Reports wurden rückwirkend auf zuvor veröffentlichte C-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
DR 321 C99 Es war unklar, ob L'x' = 'x' immer gilt
unter dem grundlegenden Zeichensatz
__STDC_MB_MIGHT_NEQ_WC__ zu diesem Zweck hinzugefügt

[bearbeiten] Referenzen

  • C23-Standard (ISO/IEC 9899:2024)
  • 6.10.4 Makroersetzung (S. 187-184)
  • 6.10.9 Vordefinierte Makronamen (S. 186-188)
  • C17-Standard (ISO/IEC 9899:2018)
  • 6.10.3 Makroersetzung (S. 121-126)
  • 6.10.8 Vordefinierte Makronamen (S. 127-129)
  • C11-Standard (ISO/IEC 9899:2011)
  • 6.10.3 Makroersetzung (S. 166-173)
  • 6.10.8 Vordefinierte Makronamen (S. 175-176)
  • C99-Standard (ISO/IEC 9899:1999)
  • 6.10.3 Makroersetzung (S. 151-158)
  • 6.10.8 Vordefinierte Makronamen (S. 160-161)
  • C89/C90-Standard (ISO/IEC 9899:1990)
  • 3.8.3 Makroersetzung
  • 3.8.8 Vordefinierte Makronamen

[bearbeiten] Siehe auch

C++ Dokumentation für Textmakroersetzung