Name | Description | Notes | Source | Availability | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|
_Generic |
Generic expression | L | + | Keyword | C11 | ||||||
default |
Default branch in _Generic
expression |
L | Keyword | C11 |
C11 introduces the ability to select different expressions based on the type of an expression, using a generic selection.
- primary-expression
-
generic-selection
since C11 - generic-selection
_Generic ( assignment-expression , generic-assoc-list )
- generic-assoc-list
generic-association
generic-assoc-list , generic-association
- generic-association
type-name : assignment-expression
default : assignment-expression
For example:
const char *y = _Generic(v, int : "%d", long : "%ld", double : "%g");
Depending on the type of the controlling expression
v
, which is not evaluated,
one of the three strings %d
,
%ld
and %g
is
chosen as the value of the generic expression. It is an error
if the type is not one of those listed, unless one of the
options is identified with
default
:
const char *y = _Generic(v, int : "%d", default : "%ld", double : "%g");
Of course, the type of v
is known
at translation time, so the selection is
made and fixed then. Furthermore, even the programmer might
know what type v
has before
translation starts, so this kind of expression might seem
redundant in this context. Two cases where it wouldn't be
redundant are when:
-
The type of the controlling expression is prone to change outside the programmer's control, especially if it is identified with a type alias.
-
The selection is within a macro definition, and the controlling expression is derived from a macro argument, so the type is not known until the macro is expanded. Macros defined in
<tgmath.h>
are likely to be covered by this case.
One issue with _Generic
is that no two options may identify the same type. So, if
size_t
is unsigned long
, the
expression _Generic(cx,
size_t : x1, unsigned long : x2)
would fail, yet it would be okay on a system where
size_t
is unsigned long long
. One
solution to this might be to cascade several generic
selections:
_Generic(cx, size_t : x1, default : _Generic(cx, unsigned long : x2))