Syntax and use of the _Generic example in C11

I heard that C11 added generics. I did a bit of searching, looked at some articles, understood the new keyword ( _Generic ) and that’s it. But I can’t understand all this.

Is this something like generics in C # or templates in C ++? Can someone give me a brief explanation of the definition of C11 generators, its syntax, and a simple example using the example?

+47
c generics c11
Mar 21 '12 at 12:11
source share
3 answers

This is a pretty good introduction. Here's an overview:

General selection is performed using the new keyword: _Generic. The syntax is similar to the syntax of a simple switch statement for types: _Generic( 'a', char: 1, int: 2, long: 3, default: 0) evaluates to 2 (character constants are ints in C).

It basically works like a switch , where labels are type names that are checked for the type of the first expression (above 'a' ). The result will be the result of evaluating _Generic() .

+34
Mar 21 '12 at 12:14
source share

The best example I saw was inspired by the following (runnable) example, which opens up all kinds of fancy possibilities for hacked introspection ...

 #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' 
+52
Jun 25 '13 at 6:19 06:19
source share

I use clion 1.2.4, and clion now does not support c11, so I use the following code in c99 instead of _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); }; 
+3
Jan 19 '16 at 13:38 on
source share



All Articles