C Language
Sélection générique
Recherche…
Syntaxe
- _Générique (expression-affectation, liste-générique-assoc)
Paramètres
Paramètre | Détails |
---|---|
liste générique-assoc | association générique OU liste générique-assoc, association générique |
association générique | nom-type: expression-assignation OU par défaut: expression-affectation |
Remarques
- Tous les qualificateurs de type seront supprimés lors de l'évaluation de l'expression primaire
_Generic
. -
_Generic
expression primaire_Generic
est évaluée à la phase de traduction 7 . Ainsi, des phases comme la concaténation de chaînes ont été terminées avant son évaluation.
Vérifier si une variable est d'un certain type qualifié
#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));
}
Sortie:
i is a const int
j is a non-const int
k is of other type
Cependant, si la macro générique de type est implémentée comme ceci:
#define is_const_int(x) _Generic((x), \
const int: "a const int", \
int: "a non-const int", \
default: "of other type")
La sortie est la suivante:
i is a non-const int
j is a non-const int
k is of other type
En effet, tous les qualificatifs de type sont supprimés pour l'évaluation de l'expression de contrôle d'une expression primaire _Generic
.
Macro d'impression de type générique
#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");
}
Sortie:
int: 42
double: 3.14
unknown argument
Notez que si le type n'est ni int
ni double
, un avertissement sera généré. Pour éliminer l'avertissement, vous pouvez ajouter ce type à la macro print(X)
.
Sélection générique basée sur plusieurs arguments
Si une sélection de plusieurs arguments pour une expression générique de type est souhaitée et que tous les types en question sont des types arithmétiques, un moyen simple d’éviter les expressions _Generic
imbriquées _Generic
à utiliser les paramètres dans l’expression de contrôle:
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))
Ici, l'expression de contrôle (X)+(Y)
n'est inspectée qu'en fonction de son type et n'est pas évaluée. Les conversions habituelles pour les opérandes arithmétiques sont effectuées pour déterminer le type sélectionné.
Pour une situation plus complexe, une sélection peut être effectuée en fonction de plusieurs arguments pour l'opérateur, en les imbriquant ensemble.
Cet exemple sélectionne entre quatre fonctions implémentées en externe, qui combinent deux arguments int et / ou chaîne et renvoient leur somme.
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 );
}
Même s'il semble que l'argument y
est évalué plus d'une fois, ce n'est pas 1 . Les deux arguments sont évalués une seule fois, à la fin de la macro Add: ( x , y )
, comme dans un appel de fonction ordinaire.
1 (Cité à partir de: ISO: IEC 9899: 201X 6.5.1.1 Sélection générique 3)
L'expression de contrôle d'une sélection générique n'est pas évaluée.