1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
<h1 id="firstHeading" class="firstHeading">Conditional inclusion</h1> <p>The preprocessor supports conditional compilation of parts of source file. This behavior is controlled by <code>#if</code>, <code>#else</code>, <code>#elif</code>, <code>#ifdef</code>, <code>#ifndef</code><span class="t-rev-inl t-since-c23"><span>, <code>#elifdef</code>, <code>#elifndef</code></span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span>, and <code>#endif</code> directives.</p>
<h3 id="Syntax"> Syntax</h3> <table class="t-sdsc-begin"> <tr class="t-sdsc"> <td> <code>#if</code> <span class="t-spar">expression</span> </td> <td class="t-sdsc-nopad"> </td> <td> </td>
</tr> <tr class="t-sdsc"> <td> <code>#ifdef</code> <span class="t-spar">identifier</span> </td> <td class="t-sdsc-nopad"> </td> <td> </td>
</tr> <tr class="t-sdsc"> <td> <code>#ifndef</code> <span class="t-spar">identifier</span> </td> <td class="t-sdsc-nopad"> </td> <td> </td>
</tr> <tr class="t-sdsc"> <td> <code>#elif</code> <span class="t-spar">expression</span> </td> <td class="t-sdsc-nopad"> </td> <td> </td>
</tr> <tr class="t-sdsc"> <td> <code>#elifdef</code> <span class="t-spar">identifier</span> </td> <td class="t-sdsc-nopad"> </td> <td> <span class="t-mark-rev t-since-c23">(since C23)</span> </td>
</tr> <tr class="t-sdsc"> <td> <code>#elifndef</code> <span class="t-spar">identifier</span> </td> <td class="t-sdsc-nopad"> </td> <td> <span class="t-mark-rev t-since-c23">(since C23)</span> </td>
</tr> <tr class="t-sdsc"> <td> <code>#else</code> </td> <td class="t-sdsc-nopad"> </td> <td> </td>
</tr> <tr class="t-sdsc"> <td> <code>#endif</code> </td> <td class="t-sdsc-nopad"> </td> <td> </td>
</tr>
</table> <h3 id="Explanation"> Explanation</h3> <p>The conditional preprocessing block starts with <code>#if</code>, <code>#ifdef</code> or <code>#ifndef</code> directive, then optionally includes any number of <code>#elif</code><span class="t-rev-inl t-since-c23"><span>, <code>#elifdef</code>, or <code>#elifndef</code></span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span> directives, then optionally includes at most one <code>#else</code> directive and is terminated with <code>#endif</code> directive. Any inner conditional preprocessing blocks are processed separately.</p>
<p>Each of <code>#if</code>, <code>#ifdef</code>, <code>#ifndef</code>, <code>#elif</code><span class="t-rev-inl t-since-c23"><span>, <code>#elifdef</code>, <code>#elifndef</code></span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span>, and <code>#else</code> directives control code block until first <code>#elif</code><span class="t-rev-inl t-since-c23"><span>, <code>#elifdef</code>, <code>#elifndef</code></span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span>, <code>#else</code>, <code>#endif</code> directive not belonging to any inner conditional preprocessing blocks.</p>
<p><code>#if</code>, <code>#ifdef</code> and <code>#ifndef</code> directives test the specified condition (see below) and if it evaluates to true, compiles the controlled code block. In that case subsequent <code>#else</code><span class="t-rev-inl t-since-c23"><span>, <code>#elifdef</code>, <code>#elifndef</code>,</span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span> and <code>#elif</code> directives are ignored. Otherwise, if the specified condition evaluates false, the controlled code block is skipped and the subsequent <code>#else</code><span class="t-rev-inl t-since-c23"><span>, <code>#elifdef</code>, <code>#elifndef</code>,</span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span> or <code>#elif</code> directive (if any) is processed. If the subsequent directive is <code>#else</code>, the code block controlled by the <code>#else</code> directive is unconditionally compiled. Otherwise, the <code>#elif</code><span class="t-rev-inl t-since-c23"><span>, <code>#elifdef</code>, or <code>#elifndef</code></span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span> directive acts as if it was <code>#if</code> directive: checks for condition, compiles or skips the controlled code block based on the result, and in the latter case processes subsequent <code>#elif</code><span class="t-rev-inl t-since-c23"><span>, <code>#elifdef</code>, <code>#elifndef</code>,</span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span> and <code>#else</code> directives. The conditional preprocessing block is terminated by <code>#endif</code> directive.</p>
<h3 id="Conditional_evaluation"> Conditional evaluation</h3> <h4 id=".23if.2C_.23elif"> <span class="co2">#if, #elif</span>
</h4> <p>The <span class="t-spar">expression</span> is a constant expression, using only <a href="../language/expressions#Constants_and_literals" title="c/language/expressions">constants</a> and identifiers, defined using <a href="replace" title="c/preprocessor/replace"><code> #define</code></a> directive. Any identifier, which is not literal, non defined using <a href="replace" title="c/preprocessor/replace"><code> #define</code></a> directive, evaluates to <code>0</code> <span class="t-rev-inl t-since-c23"><span>except <code>true</code> which evaluates to <code>1</code></span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span>.</p>
<p>The expression may contain unary operators in form <code>defined</code> <span class="t-spar">identifier</span> or <code>defined (</code><span class="t-spar">identifier</span><code>)</code> which return <code>1</code> if the <span class="t-spar">identifier</span> was defined using <a href="replace" title="c/preprocessor/replace"><code> #define</code></a> directive and <code>0</code> otherwise. <span class="t-rev-inl t-since-c23"><span>In this context, <code>__has_include</code>, <code>__has_embed</code> and <code>__has_c_attribute</code> are treated as if they were the name of defined macros.</span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span> If the <span class="t-spar">expression</span> evaluates to nonzero value, the controlled code block is included and skipped otherwise. If any used identifier is not a constant, it is replaced with <code>0</code>.</p>
<table class="t-rev-begin"> <tr class="t-rev t-since-c23">
<td> <p>In context of a preprocessor directive, a <code>__has_c_attribute</code> expression detects whether a given attribute token is supported and its supported version. See <a href="../language/attributes#Attribute_testing" title="c/language/attributes">Attribute testing</a>.</p>
</td> <td><span class="t-mark-rev t-since-c23">(since C23)</span></td>
</tr> </table> <p>Note: Until <a rel="nofollow" class="external text" href="https://open-std.org/JTC1/SC22/WG14/www/docs/dr_412.htm">DR 412</a>, <code>#if <i>cond1</i></code> ... <code>#elif <i>cond2</i></code> is different from <code>#if <i>cond1</i></code> ... <code>#else</code> followed by <code>#if <i>cond3</i></code> because if <code><i>cond1</i></code> is true, the second <code>#if</code> is skipped and <code><i>cond3</i></code> does not need to be well-formed, while <code>#elif</code>'s <code><i>cond2</i></code> must be a valid expression. As of <a rel="nofollow" class="external text" href="https://open-std.org/JTC1/SC22/WG14/www/docs/dr_412.htm">DR 412</a>, <code>#elif</code> that leads the skipped code block is also skipped.</p>
<h4 id="Combined_directives"> Combined directives</h4> <p>Checks if the identifier was <a href="replace" title="c/preprocessor/replace">defined as a macro name</a>.</p>
<p><code>#ifdef</code> <span class="t-spar">identifier</span> is essentially equivalent to <code>#if defined</code> <span class="t-spar">identifier</span>.</p>
<p><code>#ifndef</code> <span class="t-spar">identifier</span> is essentially equivalent to <code>#if !defined</code> <span class="t-spar">identifier</span>.</p>
<table class="t-rev-begin"> <tr class="t-rev t-since-c23">
<td> <p><code>#elifdef</code> <span class="t-spar">identifier</span> is essentially equivalent to <code>#elif defined</code> <span class="t-spar">identifier</span>.</p>
<p><code>#elifndef</code> <span class="t-spar">identifier</span> is essentially equivalent to <code>#elif !defined</code> <span class="t-spar">identifier</span>.</p>
</td> <td><span class="t-mark-rev t-since-c23">(since C23)</span></td>
</tr> </table> <h3 id="Notes"> Notes</h3> <p>While <code>#elifdef</code> and <code>#elifndef</code> directives target C23, implementations may backport them to the older language modes as conforming extensions.</p>
<h3 id="Example"> Example</h3> <div class="t-example"> <div class="c source-c"><pre data-language="c">#define ABCD 2
#include <stdio.h>
int main(void)
{
#ifdef ABCD
printf("1: yes\n");
#else
printf("1: no\n");
#endif
#ifndef ABCD
printf("2: no1\n");
#elif ABCD == 2
printf("2: yes\n");
#else
printf("2: no2\n");
#endif
#if !defined(DCBA) && (ABCD < 2 * 4 - 3)
printf("3: yes\n");
#endif
// C23 directives #elifdef/#elifndef
#ifdef CPU
printf("4: no1\n");
#elifdef GPU
printf("4: no2\n");
#elifndef RAM
printf("4: yes\n"); // selected in C23 mode, may be selected in pre-C23 mode
#else
printf("4: no3\n"); // may be selected in pre-C23 mode
#endif
}</pre></div> <p>Possible output:</p>
<div class="text source-text"><pre data-language="c">1: yes
2: yes
3: yes
4: yes</pre></div> </div> <h3 id="Defect_reports"> Defect reports</h3> <p>The following behavior-changing defect reports were applied retroactively to previously published C standards.</p>
<table class="dsctable"> <tr> <th>DR </th> <th>Applied to </th> <th>Behavior as published </th> <th>Correct behavior </th>
</tr> <tr> <td>
<a rel="nofollow" class="external text" href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2396.htm#dr_412">DR 412</a> </td> <td>C89 </td> <td>failed <code>#elif</code>'s expression was required to be valid </td> <td>failed <code>#elif</code> is skipped </td>
</tr>
</table> <h3 id="References"> References</h3> <ul>
<li> C23 standard (ISO/IEC 9899:2023): </li>
<ul><li> 6.10.1 Conditional inclusion (p: TBD) </li></ul>
<li> C17 standard (ISO/IEC 9899:2018): </li>
<ul><li> 6.10.1 Conditional inclusion (p: 118-119) </li></ul>
<li> C11 standard (ISO/IEC 9899:2011): </li>
<ul><li> 6.10.1 Conditional inclusion (p: 162-164) </li></ul>
<li> C99 standard (ISO/IEC 9899:1999): </li>
<ul><li> 6.10.1 Conditional inclusion (p: 147-149) </li></ul>
<li> C89/C90 standard (ISO/IEC 9899:1990): </li>
<ul><li> 3.8.1 Conditional inclusion </li></ul>
</ul> <h3 id="See_also"> See also</h3> <table class="t-dsc-begin"> <tr class="t-dsc"> <td colspan="2"> <span><a href="https://en.cppreference.com/w/cpp/preprocessor/conditional" title="cpp/preprocessor/conditional">C++ documentation</a></span> for <span class=""><span>Conditional inclusion</span></span> </td>
</tr> </table> <div class="_attribution">
<p class="_attribution-p">
© cppreference.com<br>Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.<br>
<a href="https://en.cppreference.com/w/c/preprocessor/conditional" class="_attribution-link">https://en.cppreference.com/w/c/preprocessor/conditional</a>
</p>
</div>
|