C Language
Generieke selectie
Zoeken…
Syntaxis
- _Generic (opdracht-expressie, generieke-assoc-lijst)
parameters
Parameter | Details |
---|---|
generic-assoc-lijst | generieke-associatie OF generieke-assoc-lijst, generieke-associatie |
generic-vereniging | type-naam: opdracht-uitdrukking OF standaard: opdracht-uitdrukking |
Opmerkingen
- Alle
_Generic
worden verwijderd tijdens de evaluatie van_Generic
primaire expressie. -
_Generic
primaire expressie wordt geëvalueerd in vertaalfase 7 . Dus fasen zoals string-aaneenschakeling zijn voltooid vóór de evaluatie.
Controleer of een variabele van een bepaald gekwalificeerd type is
#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));
}
Output:
i is a const int
j is a non-const int
k is of other type
Als het type generieke macro echter als volgt wordt geïmplementeerd:
#define is_const_int(x) _Generic((x), \
const int: "a const int", \
int: "a non-const int", \
default: "of other type")
De output is:
i is a non-const int
j is a non-const int
k is of other type
Dit komt omdat alle _Generic
zijn verwijderd voor de evaluatie van de controlerende expressie van een _Generic
primaire expressie.
Type-generieke afdrukmacro
#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");
}
Output:
int: 42
double: 3.14
unknown argument
Merk op dat als het type noch int
noch double
, een waarschuwing zou worden gegenereerd. Om de waarschuwing te elimineren, kunt u dat type toevoegen aan de macro voor print(X)
.
Algemene selectie op basis van meerdere argumenten
Als een selectie op meerdere argumenten voor een generieke expressie van het type gewenst is, en alle typen in kwestie rekenkundige typen zijn, is een eenvoudige manier om geneste _Generic
expressies te voorkomen het toevoegen van de parameters in de controlerende expressie:
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 wordt de controlerende expressie (X)+(Y)
alleen geïnspecteerd op basis van het type en niet geëvalueerd. De gebruikelijke conversies voor rekenkundige operanden worden uitgevoerd om het geselecteerde type te bepalen.
Voor een meer complexe situatie kan een selectie worden gemaakt op basis van meer dan één argument aan de operator, door ze samen te nestelen.
Dit voorbeeld selecteert tussen vier extern geïmplementeerde functies, die combinaties van twee int en / of stringargumenten nemen en hun som teruggeven.
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 );
}
Hoewel het lijkt alsof argument y
meer dan eens wordt geëvalueerd, is het niet 1 . Beide argumenten worden slechts eenmaal geëvalueerd, aan het einde van macro Toevoegen: ( x , y )
, net als bij een gewone functieaanroep.
1 (Geciteerd uit: ISO: IEC 9899: 201X 6.5.1.1 Algemene selectie 3)
De controlerende expressie van een generieke selectie wordt niet geëvalueerd.