2012-03-21 7 views
49

Escuché que C11 agregó genéricos. He buscado en Google un poco, he visto algunos artículos, he entendido que hay una nueva palabra clave (_Generic) y todo. Pero parece que no puedo entenderlo todo.Sintaxis y uso de muestra de _Generic en C11

¿Es algo así como los genéricos en C# o plantillas en C++? ¿Alguien puede darme una breve explicación de la definición C11 de genéricos, su sintaxis y un ejemplo simple de uso de muestras?

+3

Puede leer o descargue un [borrador del Estándar C11] (http://www.open-std.org/JTC1/sc22/wg14/www/docs/n1570.pdf) (versión PDF). Tiene un ejemplo en la sección 6.5.1.1. – pmg

+3

No existe tal cosa como "genéricos" en C++. – Griwes

+6

@Griwes aquí tienes. ¿Alguna más nitidez? – ApprenticeHacker

Respuesta

34

This es una muy buena introducción. Aquí está la información general:

La selección genérica se implementa con una nueva palabra clave: _Generic. La sintaxis es similar a una declaración simple interruptor para este tipo: _Generic('a', char: 1, int: 2, long: 3, default: 0) evalúa a 2 (constantes de caracteres son enteros en C).

Básicamente funciona como una especie de switch, en donde las marcas son nombres de los tipos que se ensayan contra el tipo de la primera expresión (el 'a' arriba). El resultado se convierte en el resultado de la evaluación de _Generic().

+1

Acabo de darme cuenta de que me vinculé a la misma página que tuviste ... No es de extrañar, sin embargo ... Es realmente el único lugar bueno para cualquier información sobre este tema, extrañamente ... –

53

The best example I have seen inspiró el ejemplo siguiente (ejecutable), que abre todo tipo de posibilidades para la introspección extraños agrietada de salida ...

#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' 
+1

wow. ¿Qué compilador usas? en mi máquina (Linux, GCC 4.9+), el último tipo se muestra como "puntero a int ': array de int es' puntero a int ' – user1284631

+0

> Apple LLVM versión 6.1.0 (clang-602.0.45) (basado en LLVM 3.6.0svn) –

+3

Esto está bien, pero nunca se puede cubrir todo tipo de esta manera ... de todos modos, +1 para "Amazeballs" ... – einpoklum

3

utilizo clion 1.2.4, y clion no es compatible con c11 ahora, entonces uso el siguiente código en c99 en lugar 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); 
}; 
Cuestiones relacionadas