Składnia i przykładowe użycie Generic w C11

Słyszałem, że C11 dodaje generyki. Trochę wygooglowałem, przejrzałem kilka artykułów, zrozumiałem, że jest nowe słowo kluczowe (_Generic ) i w ogóle. Ale nie mogę pojąć wszystkiego.

Czy to coś jak generyki w C# czy szablony w C++? Czy ktoś może mi podać krótkie wyjaśnienie definicji C11 generyków, jej składni i prostego przykładowego przykładu użycia?

Author: Sourav Ghosh, 2012-03-21

3 answers

To {[6] } jest całkiem dobrym wstępem. Oto przegląd:

Wybór generyczny jest zaimplementowany za pomocą nowego słowa kluczowego: _Generic. Składnia jest podobna do prosta instrukcja switch dla typów: _Generic( 'a', char: 1, int: 2, long: 3, default: 0) ocenia do 2 (stałe znaków są ints w C).

W zasadzie działa jak rodzaj switch, Gdzie etykiety są nazwami typów, które są testowane względem typu pierwszego wyrażenia ('a' powyżej). Wynik staje się wynikiem oceny _Generic().

 41
Author: unwind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-21 12:22:30

Najlepszy przykład jaki widziałem zainspirował poniższy (uruchamialny) przykład, który odblokowuje wszelkiego rodzaju dziwaczne możliwości pękniętej introspekcji...

#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'
 67
Author: Alex Gray,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-27 03:05:42

Używam clion 1.2.4, a clion nie obsługuje teraz c11, więc używam poniższego kodu w c99 zamiast _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);
};
 4
Author: izhkymonte,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-19 13:38:38