_Generic type-generic selection
/ JEN-er-ik /
Imagine you want one short name, say abs(x), that does the right thing whether x is an int, a long, a float, or a double, choosing a different real function for each. Plain C has no overloading, so historically you wrote a different name for each type. _Generic, added in C11, is a compile-time switch on the TYPE of an expression that lets a macro pick the matching branch.
_Generic looks like this in words: _Generic(controlling-expression, type1: result1, type2: result2, default: fallback). The compiler does not run anything; it inspects the static type of the controlling expression, matches it against the listed types, and the whole thing is REPLACED by the chosen result expression before any code runs. The controlling expression is never evaluated, only its type is examined (its lvalue-to-rvalue conversion and array/function decay are applied first). It is almost always wrapped in a macro so that one call site dispatches by type. For example, a macro cbrt(x) might select cbrtf for float, cbrt for double, and cbrtl for long double.
It matters because it is the only standard, portable way to write type-directed code in C without C++ templates or messy preprocessor tricks. The standard header <tgmath.h> is built on top of it. A common surprise: the unselected branches must still be valid expressions to the parser (they are not type-checked for the wrong types, but they must parse), and there is no implicit conversion in matching, so int and long are distinct branches even on a platform where they are the same width.
#define type_name(x) _Generic((x), int: "int", double: "double", char *: "string", default: "other") // type_name(3) -> "int" // type_name(2.0) -> "double"
A tiny type-to-string macro. The match is on the static type of the argument, decided entirely at compile time.
Matching is exact: there is no implicit conversion, so a string literal has type char[N] (often matched via char *) and a plain 'a' is int, not char — list the types you truly expect.