Name | Description | Notes | Source | Availability | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|
#elif |
Conditionally compile | L | Directive | C89 | C90 | C95 | C99 | C11 | |||
#else |
Conditionally compile | L | Directive | C89 | C90 | C95 | C99 | C11 | |||
#endif |
Conditionally compile | L | Directive | C89 | C90 | C95 | C99 | C11 | |||
#error |
Print diagnostic and fail | L | Directive | C89 | C90 | C95 | C99 | C11 | |||
#if |
Conditionally compile | L | Directive | C89 | C90 | C95 | C99 | C11 | |||
#ifdef |
Test for macro | L | Directive | C89 | C90 | C95 | C99 | C11 | |||
#ifndef |
Test for macro | L | Directive | C89 | C90 | C95 | C99 | C11 | |||
defined |
Test for macro | L | + | Native | C89 | C90 | C95 | C99 | C11 |
The directives #if
and #endif
can be used to surround a portion of text that should not
always be compiled. For example:
div_t result #if __STDC_VERSION__ > 199901 = { .quot = 10, .rem = .4 } #endif ; #if __STDC_VERSION__ <= 199901 result.quot = 10; result.rem = 4; #endif
#if
is followed by text which is subject to macro expansion and then treated as an
integer expression, which is the directive's condition. Names
in the expression that are not macros are replaced with
0
. If the condition is zero, the
enclosed text will be skipped. In our example, the text
becomes either this:
div_t result = { .quot = 10, .rem = .4 } ;
…or this:
div_t result ; result.quot = 10; result.rem = 4;
…both of which will compile in C99 or later, but the first of which will not compile in earlier versions.
Several alternative chunks of code can be selected from
using the directives #else
and #elif
:
#if condition . . . #elif condition . . . #elif condition . . . #else . . . #endif
The section of code immediately after first condition
evaluating to non-zero (true) is selected for further
processing, and the others are discarded. The optional
#else
section is used only if all conditions are false.
The code inside an unselected sectionis not completely
ignored, as nested conditional sections are permitted.
Further #if
.
. .#endif
constructs may appear in the section, and the closing
#endif
of such a construct does not prematurely terminate the
enclosing construct.
Preprocessor conditions can only be based on integer
constants, integer operators, logical operators, and macros
that expand to them. The operator defined
can also be used to test whether a macro is currently
defined:
#if defined __STDC_NO_ // We cannot use atomics. #else // We can use atomics. #endifATOMICS__
It can also be used with brackets around the macro name in question:
#if defined(__STDC_NO_ )ATOMICS__
Finally, this is such a common construct, that two more
directives exist, #ifdef
and #ifndef
:
#ifdef __STDC_NO_ // We cannot use atomics. #else // We can use atomics. #endifATOMICS__
#ifndef __STDC_NO_ // We can use atomics. #else // We cannot use atomics. #endifATOMICS__
It is not possible to use constructs such as sizeof
, that only have meaning
in later translation phases.
It's possible that a program requires some optional
feature or capability, and there's no point in trying to
build it if the feature isn't available. For this, you can
use the #error
directive, which causes an error message to be printed during
translation, and ultimately causes
translation to fail. For example, if atomics are absolutely required:
#if __STDC_VERSION__ < 201112L && defined __STDC_NO_ #error "This program needs atomics." #endifATOMICS__
#error
can also be useful for debugging. If you think a section of
source code is not actually being compiled, temporarily
insert an #error
directive, and re-compile. If you were wrong, you'll get an
error while compiling.
Name | Description | Notes | Source | Availability | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|
__DATE__ |
Compilation date | L | M | Predefined | C89 | C90 | C95 | C99 | C11 | ||
__FILE__ |
Compilation file name | L | M | Predefined | C89 | C90 | C95 | C99 | C11 | ||
__LINE__ |
Compilation line number | L | M | Predefined | C89 | C90 | C95 | C99 | C11 | ||
__STDC__ |
Indicator of conforming implementation | L | M | Predefined | C89 | C90 | C95 | C99 | C11 | ||
__STDC_ |
Indicator of analyzability | L | ? | M | Predefined | C11 | |||||
__STDC_ |
Indicator of hosted implementation | L | M | Predefined | C95 | C99 | C11 | ||||
__STDC_ |
Indicator of support for IEC 60559-compatible floating-point arithmetic | L | ? | M | Predefined | C99 | C11 | ||||
__STDC_ |
Indicator of support for IEC 60559-compatible complex arithmetic | L | ? | M | Predefined | C99 | C11 | ||||
__STDC_ |
Unicode version | L | ? | M | Predefined | C99 | C11 | ||||
__STDC_ |
Identifier of version of bounds-checking conformance | L | ? | M | Predefined | C11 | |||||
__STDC_ |
Indicator for lack of guaranteed equivalence of multibyte and wide characters in the basic character set | L | ? | M | Predefined | C11 | |||||
__STDC_ |
Indicator of lack of standard atomics | L | ? | M | Predefined | C11 | |||||
__STDC_ |
Indicator for lack of complex arithmetic | L | ? | M | Predefined | C99 | C11 | ||||
__STDC_ |
Indicator of lack of standard threading | L | ? | M | Predefined | C11 | |||||
__STDC_ |
Indicator of lack of support for variable-length arrays | L | ? | M | Predefined | C99 | C11 | ||||
__STDC_ |
Indicator of equivalence of char16_t and
UTF-16 |
L | ? | M | Predefined | C11 | |||||
__STDC_ |
Indicator of equivalence of char32_t and
UTF-32 |
L | ? | M | Predefined | C11 | |||||
__STDC_ |
Standard version identifier | L | M | Predefined | C95 | C99 | C11 | ||||
__TIME__ |
Compilation time | L | M | Predefined | C89 | C90 | C95 | C99 | C11 |
- control-line
# error pp-tokensopt new-line
- group-part
if-section
- if-section
if-group elif-groupsopt else-groupopt else-line
- if-group
# if constant-expression new-line group
# ifdef identifier new-line group
# ifndef identifier new-line group
- elif-groups
elif-group
elif-groups elif-group
- elif-group
# elif constant-expression new-line group
- else-line
# endif new-line