The preprocessor runs in phase 4 of translation. It works on tokens, not on C syntax, and knows nothing about types or scopes. It carries out the directives, expands macros, and leaves a stream of tokens for the compiler proper (C17 6.10).
Directives
A directive is a line whose first token, after any white space, is #. It ends
at the next new-line, unless that new-line was spliced with a backslash in phase 2.
White space and comments may stand before and after the #. The tokens of a
directive are not macro-expanded unless the directive says so.
| Directive | Effect | Clause | Since |
|---|---|---|---|
#include | Inserts a header or source file | 6.10.2 | K&R |
#embed | Inserts a binary file as integers | C23 | C23 |
#define | Defines a macro | 6.10.3 | K&R |
#undef | Removes a macro definition | 6.10.3.5 | K&R |
#if | Keeps a block if an expression is non-zero | 6.10.1 | K&R |
#ifdef, #ifndef | Keeps a block if a macro is, or is not, defined | 6.10.1 | K&R |
#elif | Alternative block, with an expression | 6.10.1 | C89 |
#elifdef, #elifndef | Alternative block, testing whether a macro is defined | C23 | C23 |
#else | Final alternative block | 6.10.1 | K&R |
#endif | Closes a conditional group | 6.10.1 | K&R |
#line | Sets the line number and file name | 6.10.4 | K&R |
#error | Stops translation with a message | 6.10.5 | C89 |
#warning | Issues a message and continues | C23 | C23 |
#pragma | Implementation-defined instruction | 6.10.6 | C89 |
# | The null directive: does nothing | 6.10.7 | C89 |
Clause numbers are from C17. The directives marked C23 are not in C17.
Including files
# include <h-char-sequence> new-line
# include "q-char-sequence" new-line
# include pp-tokens new-line
The whole directive is replaced by the contents of the named file, which then goes through phases 1 to 4 (C17 6.10.2). The search rules are implementation-defined:
<name>searches a list of places for a header. A standard library header need not be a file at all."name"first searches in an implementation-defined way, then falls back to the<name>search. Compilers look first in the directory of the file containing the directive.- In the third form the tokens are macro-expanded and must then match one of the first two forms.
An implementation must support at least 15 levels of nested includes. Include guards prevent repeated inclusion, as shown on the File structure page.
#embed (C23)
#embed reads a file and replaces the directive with a comma-separated list
of integer constants, one per element of the file, usually one per byte. It is intended
for initialising arrays.
| Parameter | Effect |
|---|---|
limit(n) | Uses at most n elements of the resource |
prefix(tokens) | Placed before the list if the resource is not empty |
suffix(tokens) | Placed after the list if the resource is not empty |
if_empty(tokens) | Replaces the directive if the resource is empty |
Parameters are separated by spaces, not commas. Each may appear once, and each also has a
form with double underscores, such as __limit__. An implementation may add
others.
const unsigned char icon[] = {
#embed "icon.png"
};
const char text[] = {
#embed "message.txt" if_empty('N', 'o', 'n', 'e') suffix(, 0)
};
suffix(, 0) adds a terminator only when the file is not empty__has_embed tests for a resource in an #if or
#elif expression. It returns one of three macros, and using it anywhere else
is an error:
| Macro | Value | Meaning |
|---|---|---|
__STDC_EMBED_NOT_FOUND__ | 0 | The resource was not found, or a parameter is not supported |
__STDC_EMBED_FOUND__ | 1 | The resource was found and is not empty, and all parameters are supported |
__STDC_EMBED_EMPTY__ | 2 | The resource is empty, and all parameters are supported |
Macros
# define identifier replacement-list new-line
# define identifier lparen [identifier-list] ) replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list , ... ) replacement-list new-line
# undef identifier new-line
lparen is a ( with no white space before it. This one space is what
separates the two kinds of macro: #define F(x) ... is function-like and
#define F (x) ... is object-like, replacing F with
(x) ....
A macro may be defined again only with an identical definition (C17 6.10.3). To change it,
use #undef first; #undef of an undefined name does nothing. The
macro stays defined until #undef or the end of the translation unit, and
macro definitions are not affected by block scope.
How expansion works
A function-like macro is expanded only when its name is followed by (.
Arguments are separated by commas outside matching parentheses. Expansion runs in this
order (C17 6.10.3.1, 6.10.3.4):
- Each argument is itself fully macro-expanded, unless the parameter in the replacement
list is next to
#or##. - The arguments are substituted for the parameters.
- The
#and##operators are applied. - The result is rescanned, along with the rest of the source text, for more macros to expand.
During rescanning, the name of the macro being replaced is not expanded again, and such tokens stay unavailable for later replacement. This prevents infinite recursion:
#define foo foo + 1
foo /* becomes foo + 1, with no further expansion of foo */
#define STR(x) #x
#define XSTR(x) STR(x)
STR(__LINE__) /* becomes "__LINE__" */
XSTR(__LINE__) /* becomes "12" on line 12: XSTR's argument is expanded first */
# sees itThe # operator
In a function-like macro, # before a parameter turns the argument’s tokens
into a string literal. White space between tokens becomes one space, and leading and
trailing space is removed. Backslashes and double quotes inside string literals and
character constants are escaped (C17 6.10.3.2).
The ## operator
## joins the tokens on either side into one token (C17 6.10.3.3). The result
must be a valid token, or the behaviour is undefined. The order of evaluation of several
# and ## operators is unspecified.
#define MAKE_GETTER(name) int get_##name(void) { return name; }
MAKE_GETTER(width) /* int get_width(void) { return width; } */
Variadic macros
A macro whose parameter list ends in ... takes any number of extra
arguments (C99). __VA_ARGS__ in the replacement list expands to them, commas
included. __VA_OPT__(content) (C23) expands to content only if
the variable arguments are not empty.
#define LOG(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#define SHOW(...) puts(#__VA_ARGS__)
#define CALL(f, ...) f(0 __VA_OPT__(,) __VA_ARGS__) /* C23 */
CALL(g) /* g(0) */
CALL(g, 1, 2) /* g(0, 1, 2) */
__VA_OPT__ avoids a stray comma when no arguments are givenBefore C23, the GNU extension , ##__VA_ARGS__ was the usual way to remove
the comma. It is still not standard.
Common pitfalls
#define SQUARE(x) x * x /* wrong */
SQUARE(1 + 2) /* 1 + 2 * 1 + 2, which is 5 */
#define SQUARE2(x) ((x) * (x)) /* better */
SQUARE2(i++) /* i is evaluated twice: undefined behaviour */
#define SWAP(a, b) do { int t = (a); (a) = (b); (b) = t; } while (0)
if (x) SWAP(a, b); else g(); /* the do-while makes it one statement */
do ... while (0)Conditional inclusion
if-section:
if-group {elif-group} [else-group] endif-line
if-group:
# if constant-expression new-line [group]
# ifdef identifier new-line [group]
# ifndef identifier new-line [group]
elif-group: # elif constant-expression new-line [group]
# elifdef identifier new-line [group] (C23)
# elifndef identifier new-line [group] (C23)
else-group: # else new-line [group]
endif-line: # endif new-line
The controlling expression is an integer constant expression with these changes (C17 6.10.1):
defined nameanddefined(name)evaluate to 1 or 0.- Macros in the expression are expanded.
- Any identifier left over, including keywords, is replaced by
0. Because of this, misspelled macros silently test false. In C23 the identifiertrueis replaced by1. - Signed values act as
intmax_tand unsigned values asuintmax_t.
Casts, sizeof and enumeration constants cannot be used. Character constants
are allowed, but need not match their value in the program.
Skipped groups are not processed, apart from tracking nested conditional directives. Their text must still be valid preprocessing tokens.
#if defined(__linux__) && __STDC_VERSION__ >= 201112L
#include <threads.h>
#elif defined(_WIN32)
#include <windows.h>
#else
#error "unsupported platform"
#endif
Feature test operators (C23)
| Operator | Tests |
|---|---|
__has_include(header) | Whether a header can be found; 1 or 0 |
__has_embed(header) | Whether a resource can be embedded; see #embed |
__has_c_attribute(name) | Whether an attribute is supported; a date value such as 202003L, or 0 |
Each may be used only in the expressions of #if and #elif.
#ifdef, #ifndef and defined treat them as defined,
so code can check for the operator before using it.
Line control
# line digit-sequence new-line
# line digit-sequence "s-char-sequence" new-line
# line pp-tokens new-line
#line changes what __LINE__ and __FILE__ report, and
what the compiler shows in its messages. The number applies to the following line. The
digit sequence may not be zero or greater than 2147483647 (C17 6.10.4). Tools that generate C,
such as parser generators, use it to point diagnostics at the original source file.
Error and warning
#error produces a diagnostic that includes its tokens. Since C99 the
implementation must then not translate the file successfully. #warning (C23)
also produces a message but lets translation continue.
Pragmas
# pragma [pp-tokens] new-line
_Pragma ( string-literal )
A pragma is an implementation-defined instruction. An unknown pragma is ignored by the
language, though a compiler may warn (C17 6.10.6). The tokens are not macro-expanded unless
the compiler says otherwise, and never when STDC follows
pragma.
The _Pragma operator (C99) has the same meaning but is an expression of the
preprocessor, so a macro can produce it (C17 6.10.9).
| Standard pragma | Controls | Since |
|---|---|---|
#pragma STDC FP_CONTRACT | Whether floating-point expressions may be contracted, for example into a fused multiply-add | C99 |
#pragma STDC FENV_ACCESS | Whether the code may access the floating-point environment | C99 |
#pragma STDC CX_LIMITED_RANGE | Whether complex arithmetic may use simple formulas | C99 |
#pragma STDC FENV_ROUND | The binary floating-point rounding direction for a region | C23 |
#pragma STDC FENV_DEC_ROUND | The decimal floating-point rounding direction for a region | C23 |
The first three take ON, OFF or DEFAULT.
Predefined macros
These names are defined by the implementation (C17 6.10.8). They may not be redefined or
removed with #define or #undef.
| Macro | Value | Since |
|---|---|---|
__FILE__ | The name of the current source file, as a string literal | C89 |
__LINE__ | The current line number | C89 |
__DATE__ | The date of translation, "Mmm dd yyyy" | C89 |
__TIME__ | The time of translation, "hh:mm:ss" | C89 |
__STDC__ | 1 on a conforming implementation | C89 |
__STDC_VERSION__ | 199409L (C95), 199901L (C99), 201112L (C11), 201710L (C17), 202311L (C23) | C95 |
__STDC_HOSTED__ | 1 on a hosted implementation, 0 on a freestanding one | C99 |
__STDC_UTF_16__, __STDC_UTF_32__ | 1 if char16_t and char32_t use UTF-16 and UTF-32; always 1 in C23 | C11 |
__STDC_EMBED_NOT_FOUND__, __STDC_EMBED_FOUND__, __STDC_EMBED_EMPTY__ | 0, 1 and 2; results of __has_embed | C23 |
These are defined only if the feature condition holds:
| Macro | Defined when | Since |
|---|---|---|
__STDC_ISO_10646__ | wchar_t holds ISO 10646 values; the value is a date such as 199712L | C99 |
__STDC_MB_MIGHT_NEQ_WC__ | A basic character’s wide code may differ from its ordinary code | C99 |
__STDC_IEC_559__ | IEC 60559 binary floating point is supported; deprecated in C23 | C99 |
__STDC_IEC_559_COMPLEX__ | IEC 60559 complex arithmetic is supported; deprecated in C23 | C99 |
__STDC_ANALYZABLE__ | The implementation conforms to Annex L | C11 |
__STDC_LIB_EXT1__ | The Annex K bounds-checking interfaces are available | C11 |
__STDC_NO_ATOMICS__ | Atomics are not supported | C11 |
__STDC_NO_COMPLEX__ | Complex types are not supported | C11 |
__STDC_NO_THREADS__ | <threads.h> is not supported | C11 |
__STDC_NO_VLA__ | Variable length arrays are not supported | C11 |
__STDC_IEC_60559_BFP__, __STDC_IEC_60559_DFP__, __STDC_IEC_60559_COMPLEX__, __STDC_IEC_60559_TYPES__ | The corresponding part of IEC 60559 is supported; value 202311L | C23 |
C23 also defines version macros for individual headers, such as
__STDC_VERSION_STDBIT_H__. __func__ is not a macro; it is a
predefined identifier that exists only after
preprocessing. Compilers add many macros of their own, such as __GNUC__ and
_MSC_VER.