Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Operator precedence for "<<" and "++" in VS2008 with optimization

I'm stuck with a weird VS2008 C++ issue, that looks like operator precedence is not respected.

My question is what is the output of this:

int i = 0;  
std::cout << ((i != 0) ? "Not zero " : "zero ") << ++i << std::endl;  

Normally the ++ has precedence over the <<, right? Or is the << considered like a function call giving it a higher precedence than the ++? What is the 100% correct standard answer to this?

To check, I created a new empty project (VS2008 console app), pasted only this code in the main and here are the results:

Debug|Win32: “zero 1”  
Release|Win32: “zero 1”  
Debug|x64: “zero 1”  
Release|x64: “Not zero 1”

Btw, the following example produces the exact same results:

i = 0;  
printf("%s %d\n", ((i != 0) ? "Not zero" : "zero"), ++i);  

And also changing the type of optimization in release has no effect, but disabling optimization outputs “zero 1” like other configurations.

like image 270
Nicolas Rousseau-Dupuis Avatar asked Aug 11 '10 22:08

Nicolas Rousseau-Dupuis


People also ask

What is operator precedence which operator highest precedence?

The logical-AND operator ( && ) has higher precedence than the logical-OR operator ( || ), so q && r is grouped as an operand. Since the logical operators guarantee evaluation of operands from left to right, q && r is evaluated before s-- .

What is the correct operator precedence?

The precedence of an operator specifies how "tightly" it binds two expressions together. For example, in the expression 1 + 5 * 3 , the answer is 16 and not 18 because the multiplication ("*") operator has a higher precedence than the addition ("+") operator. Parentheses may be used to force precedence, if necessary.

What is the precedence of arithmetic operators from highest to lowest?

Explanation: The Precedence of the operators is nothing but the priority given to each operator in an expression.


1 Answers

This is nothing to do with operator precedence.
You are using << which is syntactic sugar for a function call:

std::cout << ((i != 0) ? "Not zero " : "zero ") << ++i << std::endl; 

// Equivalent too:

operator<<(operator<<(operator<<(std::cout, ((i != 0) ? "Not zero " : "zero ")), ++i), std::endl);

The only rule here is that a parameter must be fully evaluated before the function is called. There are no restrictions on what order the parameters are evaluated or even if their evaluation is interleaved with calls (or even partially evaluated).

Interpretation 1:

1) ((i != 0) ? "Not zero " : "zero "))
2) ++i
3) operator<<(std::cout, (1));
4) operator<<((3), (2));
5) operator<<((4), std::endl);

Interpretation 2:

1) ++i
2) ((i != 0) ? "Not zero " : "zero "))
3) operator<<(std::cout, (2));
4) operator<<((3), (1));
5) operator<<((4), std::endl);

Interpretation 3:

1) ((i != 0) ? "Not zero " : "zero "))
2) operator<<(std::cout, (1));
3) ++i
4) operator<<((2), (3));
5) operator<<((4), std::endl);

Looking at interpretation 1 as a reference:
The rules that must be applied:

 A) (1) happens before (3)
 B) (2) happens before (4)
 C) (3) happens before (4)
 D) (4) happens before (5)
like image 82
Martin York Avatar answered Oct 24 '22 04:10

Martin York