2012-03-21 16 views
49

Ho sentito C11 aggiungere generici. Ho cercato un po 'su google, ho letto alcuni articoli, ho capito che c'è una nuova parola chiave (_Generic) e tutto il resto. Ma non riesco a cogliere tutto.Sintassi e utilizzo di esempio di _Generic in C11

È qualcosa di simile ai generici in C# o ai modelli in C++? Qualcuno può darmi una breve spiegazione della definizione di generici C11, la sua sintassi e un semplice esempio di utilizzo del campione?

+3

È possibile leggere o scarica una [bozza dello standard C11] (http://www.open-std.org/JTC1/sc22/wg14/www/docs/n1570.pdf) (versione PDF). Ha un esempio nella sezione 6.5.1.1. – pmg

+3

Non esiste una cosa come "generici" in C++. – Griwes

+6

@Griwes ecco qui. altro pignolo? – ApprenticeHacker

risposta

34

This è una buona introduzione. Ecco la panoramica:

La selezione generica è implementata con una nuova parola chiave: _Generic. La sintassi è simile a una semplice istruzione switch per i tipi: _Generic('a', char: 1, int: 2, long: 3, default: 0) valuta a 2 (le costanti di carattere sono valori in C).

pratica funziona come una specie di switch, dove le etichette sono nomi di tipo che vengono testati contro il tipo della prima espressione (il 'a' sopra). Il risultato diventa il risultato della valutazione dello _Generic().

+1

Mi sono appena reso conto che mi sono collegato alla stessa pagina che avevi .. Non c'è da stupirsi, però ... È davvero l'unico buon punto per qualsiasi informazione su questa roba, stranamente ... –

53

The best example I have seen ispirato il seguente esempio (eseguibile), che sblocca ogni sorta di possibilità Freaky per l'introspezione incrinato-out ...

#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. che compilatore usi? sulla mia macchina (Linux, GCC 4.9+), l'ultimo tipo è indicato come "puntatore a int": array di int è 'puntatore a int' – user1284631

+0

> Apple LLVM versione 6.1.0 (clang-602.0.45) (basato su LLVM 3.6.0svn) –

+3

Questo è pulito, ma non puoi mai coprire tutti i tipi in questo modo ... comunque, +1 per "Amazeball" ... – einpoklum

3

Io uso Clion 1.2.4, e Clion non supporta C11 ora, per cui uso seguente codice nel C99, invece di _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); 
}; 
Problemi correlati