diff options
Diffstat (limited to 'devdocs/gcc~13/statement-exprs.html')
| -rw-r--r-- | devdocs/gcc~13/statement-exprs.html | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/devdocs/gcc~13/statement-exprs.html b/devdocs/gcc~13/statement-exprs.html new file mode 100644 index 00000000..bb229d7f --- /dev/null +++ b/devdocs/gcc~13/statement-exprs.html @@ -0,0 +1,33 @@ +<div class="section-level-extent" id="Statement-Exprs"> <div class="nav-panel"> <p> Next: <a href="local-labels" accesskey="n" rel="next">Locally Declared Labels</a>, Up: <a href="c-extensions" accesskey="u" rel="up">Extensions to the C Language Family</a> [<a href="index#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="indices" title="Index" rel="index">Index</a>]</p> </div> <h1 class="section" id="Statements-and-Declarations-in-Expressions"><span>6.1 Statements and Declarations in Expressions<a class="copiable-link" href="#Statements-and-Declarations-in-Expressions"> ¶</a></span></h1> <p>A compound statement enclosed in parentheses may appear as an expression in GNU C. This allows you to use loops, switches, and local variables within an expression. </p> <p>Recall that a compound statement is a sequence of statements surrounded by braces; in this construct, parentheses go around the braces. For example: </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">({ int y = foo (); int z; + if (y > 0) z = y; + else z = - y; + z; })</pre> +</div> <p>is a valid (though slightly more complex than necessary) expression for the absolute value of <code class="code">foo ()</code>. </p> <p>The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire construct. (If you use some other kind of statement last within the braces, the construct has type <code class="code">void</code>, and thus effectively no value.) </p> <p>This feature is especially useful in making macro definitions “safe” (so that they evaluate each operand exactly once). For example, the “maximum” function is commonly defined as a macro in standard C as follows: </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">#define max(a,b) ((a) > (b) ? (a) : (b))</pre> +</div> <p>But this definition computes either <var class="var">a</var> or <var class="var">b</var> twice, with bad results if the operand has side effects. In GNU C, if you know the type of the operands (here taken as <code class="code">int</code>), you can avoid this problem by defining the macro as follows: </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">#define maxint(a,b) \ + ({int _a = (a), _b = (b); _a > _b ? _a : _b; })</pre> +</div> <p>Note that introducing variable declarations (as we do in <code class="code">maxint</code>) can cause variable shadowing, so while this example using the <code class="code">max</code> macro produces correct results: </p> +<div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">int _a = 1, _b = 2, c; +c = max (_a, _b);</pre> +</div> <p>this example using maxint will not: </p> +<div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">int _a = 1, _b = 2, c; +c = maxint (_a, _b);</pre> +</div> <p>This problem may for instance occur when we use this pattern recursively, like so: </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">#define maxint3(a, b, c) \ + ({int _a = (a), _b = (b), _c = (c); maxint (maxint (_a, _b), _c); })</pre> +</div> <p>Embedded statements are not allowed in constant expressions, such as the value of an enumeration constant, the width of a bit-field, or the initial value of a static variable. </p> <p>If you don’t know the type of the operand, you can still do this, but you must use <code class="code">typeof</code> or <code class="code">__auto_type</code> (see <a class="pxref" href="typeof">Referring to a Type with <code class="code">typeof</code></a>). </p> <p>In G++, the result value of a statement expression undergoes array and function pointer decay, and is returned by value to the enclosing expression. For instance, if <code class="code">A</code> is a class, then </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">A a; + +({a;}).Foo ()</pre> +</div> <p>constructs a temporary <code class="code">A</code> object to hold the result of the statement expression, and that is used to invoke <code class="code">Foo</code>. Therefore the <code class="code">this</code> pointer observed by <code class="code">Foo</code> is not the address of <code class="code">a</code>. </p> <p>In a statement expression, any temporaries created within a statement are destroyed at that statement’s end. This makes statement expressions inside macros slightly different from function calls. In the latter case temporaries introduced during argument evaluation are destroyed at the end of the statement that includes the function call. In the statement expression case they are destroyed during the statement expression. For instance, </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">#define macro(a) ({__typeof__(a) b = (a); b + 3; }) +template<typename T> T function(T a) { T b = a; return b + 3; } + +void foo () +{ + macro (X ()); + function (X ()); +}</pre> +</div> <p>has different places where temporaries are destroyed. For the <code class="code">macro</code> case, the temporary <code class="code">X</code> is destroyed just after the initialization of <code class="code">b</code>. In the <code class="code">function</code> case that temporary is destroyed when the function returns. </p> <p>These considerations mean that it is probably a bad idea to use statement expressions of this form in header files that are designed to work with C++. (Note that some versions of the GNU C Library contained header files using statement expressions that lead to precisely this bug.) </p> <p>Jumping into a statement expression with <code class="code">goto</code> or using a <code class="code">switch</code> statement outside the statement expression with a <code class="code">case</code> or <code class="code">default</code> label inside the statement expression is not permitted. Jumping into a statement expression with a computed <code class="code">goto</code> (see <a class="pxref" href="labels-as-values">Labels as Values</a>) has undefined behavior. Jumping out of a statement expression is permitted, but if the statement expression is part of a larger expression then it is unspecified which other subexpressions of that expression have been evaluated except where the language definition requires certain subexpressions to be evaluated before or after the statement expression. A <code class="code">break</code> or <code class="code">continue</code> statement inside of a statement expression used in <code class="code">while</code>, <code class="code">do</code> or <code class="code">for</code> loop or <code class="code">switch</code> statement condition or <code class="code">for</code> statement init or increment expressions jumps to an outer loop or <code class="code">switch</code> statement if any (otherwise it is an error), rather than to the loop or <code class="code">switch</code> statement in whose condition or init or increment expression it appears. In any case, as with a function call, the evaluation of a statement expression is not interleaved with the evaluation of other parts of the containing expression. For example, </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">foo (), (({ bar1 (); goto a; 0; }) + bar2 ()), baz();</pre> +</div> <p>calls <code class="code">foo</code> and <code class="code">bar1</code> and does not call <code class="code">baz</code> but may or may not call <code class="code">bar2</code>. If <code class="code">bar2</code> is called, it is called after <code class="code">foo</code> and before <code class="code">bar1</code>. </p> </div> <div class="nav-panel"> <p> Next: <a href="local-labels">Locally Declared Labels</a>, Up: <a href="c-extensions">Extensions to the C Language Family</a> [<a href="index#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="indices" title="Index" rel="index">Index</a>]</p> </div><div class="_attribution"> + <p class="_attribution-p"> + © Free Software Foundation<br>Licensed under the GNU Free Documentation License, Version 1.3.<br> + <a href="https://gcc.gnu.org/onlinedocs/gcc-13.1.0/gcc/Statement-Exprs.html" class="_attribution-link">https://gcc.gnu.org/onlinedocs/gcc-13.1.0/gcc/Statement-Exprs.html</a> + </p> +</div> |
