Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I've faced lines of code
int a=6, b=7;
cout << (b,a);
it prompt out 16.
What is (b,a) mean? Does it do a operation?
In this expression
(b,a)
there is the comma operator. Its value is the value of the last (right) subexpression after the comma. The value of the first (left) subexpression is discarded. So the output will be
6
From the C++ Standard
A pair of expressions separated by a comma is evaluated left-to-right;
the left expression is a discardedvalue expression (Clause 5).87 Every
value computation and side effect associated with the left expression
is sequenced before every value computation and side effect associated
with the right expression. The type and value of the result are the
type and value of the right operand; the result is of the same value
category as its right operand, and is a bit-field if its right operand
is a glvalue and a bit-field. If the value of the right operand is a
temporary (12.2), the result is that temporary.
Related
I know two things about the built-in postfix increment operator:
Firstly the result value is evaluated (i.e. prvalue copy of the operand is created).
Only after that the side effect (increment) is applied to the original object.
So when exactly this operator returns the result? I see three options here:
a) immediately after its evaluation
(i.e. after 1. In this case "returning the result" is equivalent to "evaluate the result")
b) in some moment between 1. and 2.
c) after completion of the side effect (after 2.)?
Which option is technically correct?
Edit: Maybe this question refers to more general question:
"returning the result of operator/expression" is the same thing as "evaluating the result of operator/expression" or not?
P.S. I know this is a stupid question but I didn't find answer to it. It bothers me because there are other operators (and expressions) with side effects which are completed after evaluating result.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I am now in the midst of making a simple bytecode interpreter that uses RPN for expression notation and really postfix notation for anything, but now I've come to the question which is: can short circuit evaluation actually be used on postfix expressions? For example when evaluating the expression (false && (factorial(7) > factorial(5))) C++ knows the result of the && operator on the two operands evaluates to false before it even gets to the second operand, since (false && anything) is always equal to false. Now when you put this in RPN, you get (false (7 factorial 5 factorial >) &&).
I wanted to build an efficient RPN expression parser, so the problem is this: how do I make an efficient RPN expression parser with short circuit evaluation?
You would evaluate an RPN expression in two phases.
Phase 1: parse the RPN, and construct a tree representation of the RPN. So, in this tree, for example, the && node has two children nodes, for each half of the expression. Constructing this tree is a nearly identical process as evaluating the RPN, except for the evaluating part, which gets replaced by the operation of constructing a new node, and linking its child nodes to their new parent node, then pushing the parent node back on the RPN evaluation stack.
Phase 2: evaluate the constructed tree, using recursive descent. At this point, short-circuit evaluation becomes trivial: evaluate the left-hand child of a &&, then decide whether you actually want to evaluate the right-hand child.
Ditto for the || node, etc...
I already checked some other answers like:
Sequence point within assignment operators
or
Undefined behavior and sequence points
but I have still some doubt about the following part:
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.
It is not clear for me what is the "value computation of the assignment expression". Is it just (referring to the first link) "show" the number stored in the variable?
This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 7 years ago.
Here is my code :
b = f() || b;
The function f() has side effect and it must be always executed. Normally, only the right operand can be short-circuited and this code should work. But I am afraid some compilators reverse the two operands, since it's more efficient to short-circuit a function evaluation rather than a simple variable evaluation. I know that g++ -O3 can break some specifications, but I don't know if this code can be affected.
So, is my code risk-free?
I knew Is short-circuiting logical operators mandated? And evaluation order? but my question was about compilers optimizations, I didn't know that they can't break the standards (even if this would be strange).
But I am afraid some compilators reverse the two operands
These expressions must be evaluated left-to-right. This is covered in the standard about the operators &&, ||, ?, and ,. They specifically mention the order, as well as enforced sequence points.
§5.14.1 (Logical AND)
The && operator groups left-to-right. The operands are both contextually converted to bool (Clause 4). The result is true if both operands are true and false otherwise. Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
§5.15.1 (Logical OR)
The || operator groups left-to-right. The operands are both contextually converted to bool (Clause 4). It returns true if either of its operands is true, and false otherwise. Unlike |, || guarantees left-to-right evaluation; moreover, the second operand is not evaluated if the first operand evaluates to true.
§5.16.1 (Conditional operator)
Conditional expressions group right-to-left. The first expression is contextually converted to bool (Clause 4). It is evaluated and if it is true, the result of the conditional expression is the value of the second expression,
otherwise that of the third expression. Only one of the second and third expressions is evaluated. Every value computation and side effect associated with the first expression is sequenced before every value computation
and side effect associated with the second or third expression.
§5.19.1 (Comma operator)
The comma operator groups left-to-right. A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded value
expression (Clause 5). Every value computation and side effect associated with the left expression is sequenced before every value computation and side effect associated with the right expression. The type and value of the result are the type and value of the right operand; the result is of the same value category
as its right operand, and is a bit-field if its right operand is a glvalue and a bit-field. If the value of the right operand is a temporary (12.2), the result is that temporary.
Regarding your concern about optimizations violating this order, no compilers are not allowed to change the order. Compilers must first and foremost (try to) follow the standard. Then they can try to make your code faster. They may not violate the standard just for the sake of performance. That undermines the entire premise of having a standard.
It's explicitly stated by the standard that optimized code should behave "as-if" it was exactly the code that was written, as long as you only rely on standard behavior.
Since the standard requires the boolean statements to be evaluated from left to right, no (compliant) optimization can change the order of evaluation.
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 8 years ago.
Firstly, this is an attempt to understand how operator precedence works and not being used by me in any of my projects.
int *a=new int[3];
a[0]=3;a[1]=7;a[2]=11;
*a*=++*a**a++;
cout<<*(a-1)<<endl<<*a<<endl<<*(a+1);
Gives the following output,
4
112
11
I am expecting the following output,
64
7
11
Can someone please tell me how this is happening?
Thank you
Even by respecting operator precedences, you're not respecting sequence points and thus invoking undefined behavior.
Take a look at the cpp faq here: http://www.parashift.com/c++-faq/sequence-points.html
The C++ standard says (1.9p7),
At certain specified points in the execution sequence called sequence
points, all side effects of previous evaluations shall be complete and
no side effects of subsequent evaluations shall have taken place.
For example, if an expression contains the subexpression y++, then the
variable y will be incremented by the next sequence point. Furthermore
if the expression just after the sequence point contains the
subexpression ++z, then z will not have yet been incremented at the
moment the sequence point is reached.
The order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified
Additional info on sequence points: https://stackoverflow.com/a/4176333/1938163