You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Primary expressions are the building blocks of more complex expressions. They may be constants, identifiers, and in C11, a [Generic selection](generic_selection.md). An expression in parentheses is also a primary expression.
9
+
Primary expressions are the building blocks of more complex expressions. They may be constants, identifiers, and in C11, a [Generic selection](generic_selection.md). An expression in parentheses is also a primary expression.
Use the _Generic keyword to select an expression at compile time, based on a type.
10
+
Use the **`_Generic`** keyword to write code that makes a compile time decision based on the type of the argument.
11
+
12
+
**`_Generic`** selects an expression based on a type at compile time. It is somewhat similar to overloading in C++ where the type of the argument is used to select which function to call. In this case, the type of the argument selects which expression to evaluate.
13
+
14
+
For example, the expression `_Generic(42, int:"integer", char:"character", default:"unknown");` evaluates the type of `42` and looks for the matching type, `int` in the list. It will find it and return `"integer"`.
The first *`assignment-expression`* is called the controlling expression. The controlling expression is evaluated at compile time and matched against the *`assoc-list`* to find which expression to evaulate and return.
30
+
31
+
When the controlling expression is evaluated, `const`, `volatile`, and `restrict` are removed before matching against *`assoc-list`*.
32
+
33
+
Entries in the `assoc-list` that are not chosen are not evaluated.
34
+
35
+
## Constraints
36
+
37
+
- The *`assoc-list`* can't specify the same type more than once.
38
+
- The *`assoc-list`* can't specify types that are compatible with each other, such as an enumeration and the underlying type of that enumeration.
39
+
- If a generic selection doesn't have a default, the controlling expression must have only one compatible type name in the generic association list.
40
+
41
+
## Example
42
+
43
+
One way to use **`_Generic`** is in a macro. The <tgmath.h> header file uses **_Generic** to call the right math function depending on the type of argument. For example, the macro for `cos()` maps a call with a float to `cosf()`, whereas a call with a complex double is mapped to `ccos()`.
44
+
45
+
The following example shows how to write a macro that identifies the type of the argument you pass to it. It produces `"unknown"` if no entry in the *`assoc-list`* matches the controlling expression:
46
+
47
+
```C
48
+
// Compile with /std:c11
11
49
12
-
```c
13
50
#include<stdio.h>
14
-
#include<stddef.h>
15
-
#include<stdint.h>
16
-
17
-
#definetypename(x) _Generic((x), /* Get the name of a type */ \
18
-
\
19
-
_Bool: "_Bool", unsigned char: "unsigned char", \
20
-
char: "char", signed char: "signed char", \
21
-
short int: "short int", unsigned short int: "unsigned short int", \
22
-
int: "int", unsigned int: "unsigned int", \
23
-
long int: "long int", unsigned long int: "unsigned long int", \
24
-
long long int: "long long int", unsigned long long int: "unsigned long long int", \
25
-
float: "float", double: "double", \
26
-
long double: "long double", char *: "pointer to char", \
27
-
void *: "pointer to void", int *: "pointer to int", \
28
-
default: "other")
51
+
52
+
/* Get a type name string for the argument x */
53
+
#defineTYPE_NAME(X) _Generic((X), \
54
+
int: "int", \
55
+
char: "char", \
56
+
double: "double", \
57
+
default: "unknown")
58
+
59
+
intmain()
60
+
{
61
+
printf("Type name: %s\n", TYPE_NAME(42.42));
62
+
63
+
// The following results in a compile error because
64
+
// 42.4 is a double, doesn't match anything in the list,
0 commit comments