diff options
| author | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
| commit | 754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch) | |
| tree | f1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/c/preprocessor%2Fconditional.html | |
new repository
Diffstat (limited to 'devdocs/c/preprocessor%2Fconditional.html')
| -rw-r--r-- | devdocs/c/preprocessor%2Fconditional.html | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/devdocs/c/preprocessor%2Fconditional.html b/devdocs/c/preprocessor%2Fconditional.html new file mode 100644 index 00000000..2b4496f2 --- /dev/null +++ b/devdocs/c/preprocessor%2Fconditional.html @@ -0,0 +1,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> |
