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

  1. Tous les qualificateurs de type seront supprimés lors de l'évaluation de l'expression primaire _Generic .
  2. _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.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow