71 votes

Syntaxe et exemple d'utilisation de _Generic dans C11

J'ai entendu que C11 avait ajouté des génériques. J'ai un peu cherché sur Google, regardé quelques articles, compris qu'il y avait un nouveau mot-clé ( _Generic ) et tout. Mais je n'arrive pas à tout saisir.

Est-ce quelque chose comme les génériques en C# ou les modèles en C++ ? Quelqu'un peut-il me donner une brève explication de la définition C11 des génériques, sa syntaxe et un exemple d'utilisation simple ?

100voto

alex gray Points 5089

Le meilleur exemple que j'ai vu a inspiré l'exemple (exécutable) suivant, qui ouvre toutes sortes de possibilités bizarres pour une introspection déchaînée...

 #include <stdio.h>
#include <stddef.h>
#include <stdint.h>

#define typename(x) _Generic((x),        /* Get the name of a type */             \
                                                                                  \
        _Bool: "_Bool",                  unsigned char: "unsigned char",          \
         char: "char",                     signed char: "signed char",            \
    short int: "short int",         unsigned short int: "unsigned short int",     \
          int: "int",                     unsigned int: "unsigned int",           \
     long int: "long int",           unsigned long int: "unsigned long int",      \
long long int: "long long int", unsigned long long int: "unsigned long long int", \
        float: "float",                         double: "double",                 \
  long double: "long double",                   char *: "pointer to char",        \
       void *: "pointer to void",                int *: "pointer to int",         \
      default: "other")

#define fmt "%20s is '%s'\n"
int main() {

  size_t s; ptrdiff_t p; intmax_t i; int ai[3] = {0}; return printf( fmt fmt fmt fmt fmt fmt fmt fmt,

     "size_t", typename(s),               "ptrdiff_t", typename(p),     
   "intmax_t", typename(i),      "character constant", typename('0'),
 "0x7FFFFFFF", typename(0x7FFFFFFF),     "0xFFFFFFFF", typename(0xFFFFFFFF),
"0x7FFFFFFFU", typename(0x7FFFFFFFU),  "array of int", typename(ai));
}
                  ╔═══════════════╗ 
═════════════════╣ Amazeballs... ╠═════════════════════════════════════
                 ╚═══════════════╝ 
            size_t is 'unsigned long int'
         ptrdiff_t is 'long int'
          intmax_t is 'long int'
character constant is 'int'
        0x7FFFFFFF is 'int'
        0xFFFFFFFF is 'unsigned int'
       0x7FFFFFFFU is 'unsigned int'
      array of int is 'other'

6voto

izhkymonte Points 147

J'utilise clion 1.2.4, et clion ne prend pas en charge c11 maintenant, j'utilise donc le code suivant dans c99 au lieu de _Generic

 #include <stdio.h>

int main(int argc, char **argv) {
    char *s;
    if (__builtin_types_compatible_p(__typeof__(s), long)) {
        puts("long");
    } else if (__builtin_types_compatible_p(__typeof__(s), char*)) {
        puts("str");
    }
    return (0);
};

5voto

larsmans Points 167484

À en juger par l'exemple donné sur Wikipedia , il peut être utilisé pour obtenir quelque chose de similaire à la surcharge de C++ :

la macro suivante cbrt(x) traduit par cbrtl(x) , cbrt(x) ou cbrtf(x) selon le type de x :

 #define cbrt(X) _Generic((X), long double: cbrtl, \
                              default: cbrt, \
                              float: cbrtf)(X)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X