Skip to content

Commit a5efd56

Browse files
TylerMSFTTylerMSFT
authored andcommitted
first draft
1 parent 971985b commit a5efd56

File tree

2 files changed

+72
-27
lines changed

2 files changed

+72
-27
lines changed

docs/c-language/c-primary-expressions.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,20 @@ helpviewer_keywords: ["primary expressions"]
66
---
77
# C primary expressions
88

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.
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.
1010

1111
## Syntax
1212

13-
*primary-expression*:\
14-
    *identifier*\
15-
    *constant*\
16-
    *string-literal*\
17-
    *_Generic(assignment expression, generic-assoc-list)*\
18-
    **(** *expression* **)**
13+
*`primary-expression`*:\
14+
    *`identifier`*\
15+
    *`constant`*\
16+
    *`string-literal`*\
17+
    **(** *`expression`* **)**\
18+
    *`generic-selection`*
1919

2020
*expression*:\
21-
    *assignment-expression*\
22-
    *expression* **,** *assignment-expression*
21+
    *`assignment-expression`*\
22+
    *`expression`***,** *`assignment-expression`*
2323

2424
## See also
2525

docs/c-language/generic_selection.md

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,72 @@ helpviewer_keywords: ["_Generic keyword [C]"]
77

88
# Generic Selection (C11)
99

10-
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"`.
15+
16+
## Syntax
17+
18+
*`generic-selection`*:\
19+
    **`_Generic`** **(** *`assignment-expression`, `assoc-list`* **)**
20+
21+
*`assoc-list`*:\
22+
    *`association`*\
23+
    *`assoc-list`, `association`*
24+
25+
*`association`*:\
26+
    *`type-name`* : *`assignment-expression`*\
27+
    **`default`** : *`assignment-expression`*
28+
29+
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
1149

12-
```c
1350
#include <stdio.h>
14-
#include <stddef.h>
15-
#include <stdint.h>
16-
17-
#define typename(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+
#define TYPE_NAME(X) _Generic((X), \
54+
int: "int", \
55+
char: "char", \
56+
double: "double", \
57+
default: "unknown")
58+
59+
int main()
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,
65+
// and there is no default.
66+
// _Generic(42.4, int:"integer", char : "character"));
67+
}
68+
69+
/* Output:
70+
Type name: double
71+
*/
72+
2973
```
3074

3175
## See also
3276

33-
[`/std` (Specify Language Standard Version)](../build/reference/std-specify-language-standard-version.md)\
77+
[`/std` (Specify Language Standard Version)](../build/reference/std-specify-language-standard-version.md)\
78+
[Type-generic math](../cpp/c-runtime-library/tgmath.md)

0 commit comments

Comments
 (0)