Note that there are some explanatory texts on larger screens.

plurals
  1. POOperator Precedence vs Order of Evaluation
    primarykey
    data
    text
    <p>The terms 'operator precedence' and 'order of evaluation' are very commonly used terms in programming and extremely important for a programmer to know. And, as far as I understand them, the two concepts are tightly bound; one cannot do without the other when talking about expressions.</p> <p>Let us take a simple example:</p> <pre><code>int a=1; // Line 1 a = a++ + ++a; // Line 2 printf("%d",a); // Line 3 </code></pre> <p>Now, it is evident that <code>Line 2</code> leads to Undefined Behavior, since <strong><a href="http://en.wikipedia.org/wiki/Sequence_point" rel="noreferrer">Sequence points in C and C++</a></strong> include:</p> <blockquote> <ol> <li><p>Between evaluation of the left and right operands of the &amp;&amp; (logical AND), || (logical OR), and comma operators. For example, in the expression <code>*p++ != 0 &amp;&amp; *q++ != 0</code>, all side effects of the sub-expression <code>*p++ != 0</code> are completed before any attempt to access <code>q</code>.</p></li> <li><p>Between the evaluation of the first operand of the ternary "question-mark" operator and the second or third operand. For example, in the expression <code>a = (*p++) ? (*p++) : 0</code> there is a sequence point after the first <code>*p++</code>, meaning it has already been incremented by the time the second instance is executed.</p></li> <li><p>At the end of a full expression. This category includes expression statements (such as the assignment <code>a=b;</code>), return statements, the controlling expressions of if, switch, while, or do-while statements, and all three expressions in a for statement.</p></li> <li><p>Before a function is entered in a function call. The order in which the arguments are evaluated is not specified, but this sequence point means that all of their side effects are complete before the function is entered. In the expression <code>f(i++) + g(j++) + h(k++)</code>, <code>f</code> is called with a parameter of the original value of <code>i</code>, but <code>i</code> is incremented before entering the body of <code>f</code>. Similarly, <code>j</code> and <code>k</code> are updated before entering <code>g</code> and <code>h</code> respectively. However, it is not specified in which order <code>f()</code>, <code>g()</code>, <code>h()</code> are executed, nor in which order <code>i</code>, <code>j</code>, <code>k</code> are incremented. The values of <code>j</code> and <code>k</code> in the body of <code>f</code> are therefore undefined.<a href="http://en.wikipedia.org/wiki/Sequence_point" rel="noreferrer">3</a> Note that a function call <code>f(a,b,c)</code> is not a use of the comma operator and the order of evaluation for <code>a</code>, <code>b</code>, and <code>c</code> is unspecified.</p></li> <li><p>At a function return, after the return value is copied into the calling context. (This sequence point is only specified in the C++ standard; it is present only implicitly in C.)</p></li> <li><p>At the end of an initializer; for example, after the evaluation of 5 in the declaration <code>int a = 5;</code>.</p></li> </ol> </blockquote> <p>Thus, going by Point # 3:</p> <p><em>At the end of a full expression. This category includes expression statements (such as the assignment a=b;), return statements, the controlling expressions of if, switch, while, or do-while statements, and all three expressions in a for statement.</em></p> <p><code>Line 2</code> clearly leads to Undefined Behavior. This shows how <strong>Undefined Behaviour</strong> is tightly coupled with <strong>Sequence Points</strong>.</p> <p>Now let us take another example:</p> <pre><code>int x=10,y=1,z=2; // Line 4 int result = x&lt;y&lt;z; // Line 5 </code></pre> <p>Now its evident that <code>Line 5</code> will make the variable <code>result</code> store <code>1</code>.</p> <p>Now the expression <code>x&lt;y&lt;z</code> in <code>Line 5</code> can be evaluated as either:</p> <p><code>x&lt;(y&lt;z)</code> or <code>(x&lt;y)&lt;z</code>. In the first case the value of <code>result</code> will be <code>0</code> and in the second case <code>result</code> will be <code>1</code>. But we know, when the <code>Operator Precedence</code> is <code>Equal/Same</code> - <code>Associativity</code> comes into play, hence, is evaluated as <code>(x&lt;y)&lt;z</code>.</p> <p>This is what is said in this <a href="http://msdn.microsoft.com/en-us/library/2bxt6kc4.aspx" rel="noreferrer">MSDN Article</a>:</p> <p><em>The precedence and associativity of C operators affect the grouping and evaluation of operands in expressions. An operator's precedence is meaningful only if other operators with higher or lower precedence are present. Expressions with higher-precedence operators are evaluated first. Precedence can also be described by the word "binding." Operators with a higher precedence are said to have tighter binding.</em></p> <p>Now, about the above article:</p> <p><em>It mentions "Expressions with higher-precedence operators are evaluated first."</em></p> <p>It may sound incorrect. But, I think the article is not saying something wrong if we consider that <code>()</code> is also an operator <code>x&lt;y&lt;z</code> is same as <code>(x&lt;y)&lt;z</code>. My reasoning is if associativity does not come into play, then the complete expressions evaluation would become ambiguous since <code>&lt;</code> is not a <a href="http://en.wikipedia.org/wiki/Sequence_point" rel="noreferrer"><strong>Sequence Point</strong></a>.</p> <p>Also, another link I found says this on <a href="http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm" rel="noreferrer">Operator Precedence and Associativity</a>:</p> <p><em>This page lists C operators in order of precedence (highest to lowest). Their associativity indicates in what order operators of equal precedence in an expression are applied.</em></p> <p>So taking, the second example of <code>int result=x&lt;y&lt;z</code>, we can see here that there are in all 3 expressions, <code>x</code>, <code>y</code> and <code>z</code>, since, the simplest form of an expression consists of a single literal constant or object. Hence the result of the expressions <code>x</code>, <code>y</code>, <code>z</code> would be there <strong>rvalues</strong>, i.e., <code>10</code>, <code>1</code> and <code>2</code> respectively. Hence, now we may interpret <code>x&lt;y&lt;z</code> as <code>10&lt;1&lt;2</code>. </p> <p>Now, doesn't Associativity come into play since now we have 2 expressions to be evaluated, either <code>10&lt;1</code> or <code>1&lt;2</code> and since the precedence of operator is same, <em>they are evaluated from left to right</em>?</p> <p>Taking this last example as my argument:</p> <pre><code>int myval = ( printf("Operator\n"), printf("Precedence\n"), printf("vs\n"), printf("Order of Evaluation\n") ); </code></pre> <p>Now in the above example, since the <code>comma</code> operator has same precedence, the expressions are evaluated <code>left-to-right</code> and the return value of the last <code>printf()</code> is stored in <code>myval</code>.</p> <p>In <a href="http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1336.pdf" rel="noreferrer">SO/IEC 9899:201x</a> under <strong>J.1 Unspecified behavior</strong> it mentions:</p> <p><em>The order in which subexpressions are evaluated and the order in which side effects take place, except as specified for the function-call (), &amp;&amp;, ||, ?:, and comma operators (6.5).</em></p> <p>Now I would like to know, would it be wrong to say:</p> <p><em>Order of Evaluation depends on the precedence of operators, leaving cases of Unspecified Behavior.</em></p> <p>I would like to be corrected if any mistakes were made in something I said in my question. The reason I posted this question is because of the confusion created in my mind by the MSDN Article. Is it in <strong>Error</strong> or not?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload