C Language
Generische Auswahl
Suche…
Syntax
- _Generic (Zuweisungsausdruck, generische Assoc-Liste)
Parameter
Parameter | Einzelheiten |
---|---|
generische assoc-liste | generic-association ODER generic-assoc-liste, generic-association |
generische Vereinigung | Typname: Zuweisungsausdruck ODER Standard: Zuweisungsausdruck |
Bemerkungen
- Alle
_Generic
werden während der Auswertung des_Generic
Primärausdrucks_Generic
. -
_Generic
Primärausdruck wird in Übersetzungsphase 7 ausgewertet. Daher wurden Phasen wie die Verkettung von Strings vor der Auswertung abgeschlossen.
Prüfen Sie, ob eine Variable einen bestimmten qualifizierten Typ hat
#include <stdio.h>
#define is_const_int(x) _Generic((&x), \
const int *: "a const int", \
int *: "a non-const int", \
default: "of other type")
int main(void)
{
const int i = 1;
int j = 1;
double k = 1.0;
printf("i is %s\n", is_const_int(i));
printf("j is %s\n", is_const_int(j));
printf("k is %s\n", is_const_int(k));
}
Ausgabe:
i is a const int
j is a non-const int
k is of other type
Wenn jedoch das generische Typmakro folgendermaßen implementiert ist:
#define is_const_int(x) _Generic((x), \
const int: "a const int", \
int: "a non-const int", \
default: "of other type")
Die Ausgabe ist:
i is a non-const int
j is a non-const int
k is of other type
Dies liegt daran, dass alle _Generic
für die Auswertung des steuernden Ausdrucks eines _Generic
Primärausdrucks _Generic
.
Typisches generisches Druckmakro
#include <stdio.h>
void print_int(int x) { printf("int: %d\n", x); }
void print_dbl(double x) { printf("double: %g\n", x); }
void print_default() { puts("unknown argument"); }
#define print(X) _Generic((X), \
int: print_int, \
double: print_dbl, \
default: print_default)(X)
int main(void) {
print(42);
print(3.14);
print("hello, world");
}
Ausgabe:
int: 42
double: 3.14
unknown argument
Wenn der Typ weder int
noch double
, wird eine Warnung generiert. Um die Warnung zu beseitigen, können Sie diesen Typ zum Makro print(X)
hinzufügen.
Generische Auswahl basierend auf mehreren Argumenten
Wenn eine Auswahl mehrerer Argumente für einen generischen _Generic
gewünscht wird und alle _Generic
Typen arithmetische Typen sind, können verschachtelte _Generic
Ausdrücke auf einfache Weise _Generic
indem die Parameter im steuernden Ausdruck _Generic
:
int max_int(int, int);
unsigned max_unsigned(unsigned, unsigned);
double max_double(double, double);
#define MAX(X, Y) _Generic((X)+(Y), \
int: max_int, \
unsigned: max_unsigned, \
default: max_double) \
((X), (Y))
Hier wird der steuernde Ausdruck (X)+(Y)
nur nach Typ geprüft und nicht ausgewertet. Die üblichen Konvertierungen für arithmetische Operanden werden durchgeführt, um den ausgewählten Typ zu bestimmen.
In einer komplexeren Situation kann eine Auswahl auf der Grundlage mehrerer Argumente für den Bediener getroffen werden, indem diese verschachtelt werden.
In diesem Beispiel werden vier extern implementierte Funktionen ausgewählt, die Kombinationen von zwei Argumenten int und / oder string annehmen und deren Summe zurückgeben.
int AddIntInt(int a, int b);
int AddIntStr(int a, const char* b);
int AddStrInt(const char* a, int b );
int AddStrStr(const char* a, const char* b);
#define AddStr(y) \
_Generic((y), int: AddStrInt, \
char*: AddStrStr, \
const char*: AddStrStr )
#define AddInt(y) \
_Generic((y), int: AddIntInt, \
char*: AddIntStr, \
const char*: AddIntStr )
#define Add(x, y) \
_Generic((x) , int: AddInt(y) , \
char*: AddStr(y) , \
const char*: AddStr(y)) \
((x), (y))
int main( void )
{
int result = 0;
result = Add( 100 , 999 );
result = Add( 100 , "999" );
result = Add( "100" , 999 );
result = Add( "100" , "999" );
const int a = -123;
char b[] = "4321";
result = Add( a , b );
int c = 1;
const char d[] = "0";
result = Add( d , ++c );
}
Obwohl es so aussieht, als würde Argument y
mehr als einmal ausgewertet, ist es nicht 1 . Beide Argumente werden nur einmal am Ende des Makros Add: ( x , y )
ausgewertet, genau wie bei einem normalen Funktionsaufruf.
1 (Zitiert aus: ISO: IEC 9899: 201X 6.5.1.1 Generische Auswahl 3)
Der steuernde Ausdruck einer generischen Auswahl wird nicht ausgewertet.