How does this piece of code work? - c++

1.)
int i;
for(i=1;i<5,i<8;i++){
}
printf("%d",i);
2.)
int i;
for(i=1;i<18,i<6;i++){
}
printf("%d",i);
output for 1.) is 8 while for 2.) is 6
I am not getting how the code works, Help will be highly appreciated.

The , operator evaluates to its last operand.
i < 18, i < 6 becomes false when i is 6.

Comma operator ( , )
The comma operator (,) is used to separate two or more expressions that are included where only one expression is expected. When the set of expressions has to be evaluated for a value, only the rightmost expression is considered.
Hence:
for(i=1;i<5,i<8;i++)
is equivalent to:
for(i=1;i<8;i++)
Which evaluates value of i to 8
And
for(i=1;i<18,i<6;i++)
is equivalent to:
for(i=1;i<6;i++)
Which evaluates value of i to 6
Standerdese Reference:
C++11 Standard §5.18:
The comma operator groups left-to-right.
expression:
assignment-expression
expression , assignment-expression
A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded- value expression (Clause 5)83. 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.

Related

Post-increment operator behaviour w.r.t comma operator?

In the following code:
int main() {
int i, j;
j = 10;
i = (j++, j+100, 999+j);
cout << i;
return 0;
}
The output is 1010.
However shouldn't it be 1009, as ++ should be done after the whole expression is used?
The comma operator is a sequence point: as it says in the C++17 standard for example,
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.
Thus, the effect of the ++ operator is guaranteed to occur before 999+j is evaluated.
++ should be done after the whole expression is used?
No. The postfix operator evaluates to the value of the old j and has the side effect of incrementing j.
Comma operator evaluates the second operand after the first operand is evaluated and its side-effects are evaluated.
A pair of expressions separated by a comma is evaluated left-to-right;
the left expression is a discarded- value expression (Clause 5)83.
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.
https://stackoverflow.com/a/7784819/2805305
Associativity of the comma operator is left to right.
So starting from j++, this will be evaluated first (j becomes 11)
Then j + 100 is evaluated (no use)
Then 999 + j is evaluated which is equal to 1010
This rightmost value is assigned to i
Thus, the output is 1010
Long Answer:
Built-in comma operator
The comma operator expressions have the form
E1 , E2
In a comma expression E1, E2, the expression E1 is evaluated, its
result is discarded (although if it has class type, it won't be
destroyed until the end of the containing full expression), and its
side effects are completed before evaluation of the expression E2
begins (note that a user-defined operator, cannot guarantee
sequencing) (until C++17).
This already answers your question, but I'll walk through it with reference to your code:
Start with something simple like
int value = (1 + 2, 2 + 3, 4 + 5); // value is assigned 9
Because ...the expression E1 is evaluated, its result is discarded... Here, since we have more than 2 operands, the associativity of the comma operator also comes into play.
However shouldn't it be 1009, as '++" should be done after the whole
expression is used?
Now see:
int j = 0;
int i = (j++, 9 + j);
Here, the value of i is 10 because ...and its side effects are completed before evaluation of the expression E2 begins... Hence, the incrementation of j has its effect before the evaluation of 9 + j.
I think now you can clearly understand why your
j = 10;
i = (j++, j+100, 999+j);
i is assigned a value of 1010.

Round bracket apparent syntactic error in C++ but compiler not complaining

Why the compiler (g++-4.9) is not complaining on this notation?
double d=(4,5,6);
and if I debug it, the value of d is 6?
What do the round brackets mean in this expression?
P.S.
I've enabled C++11
This uses the comma operator, which (without overloading) just evaluates the left-hand expression, throws away the result, and returns the result of the right-hand expression.
Since the expressions 4 and 5 have no side-effects, your code is equivalent to:
double d = 6;
This is comma operator.
In a comma expression E1, E2, the expression E1 is evaluated, its
result is discarded, and its side effects are completed before
evaluation of the expression E2 begins (note that a user-defined
operator, cannot guarantee sequencing).
For (4,5,6), first evaluate expression 4, disregard its return value and complete any side-effects (nothing here indeed), then do the same thing with 5, then evaluate the last expression 6, returning the type and the result of this evaluation.

Does the ternary operator short circuit in a defined way

If you have the following:
if (x)
{
y = *x;
}
else
{
y = 0;
}
Then behavior is guaranteed to be defined since we can only dereference x if it is not 0
Can the same be said for:
y = (x) ? *x : 0;
This seems to work as expected (even compiled with -Wpedantic on g++)
Is this guaranteed?
Yes, only the second or third operand will be evaluated, the draft C++ standard section 5.16 [expr.cond] says:
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.

Can someone clear this concept for the output I am getting?

This has been asked in an interview. What is the output of the below snippet?
#include <iostream>
using namespace std;
int main() {
cout << (3,2,1)-(1,2,3) << endl; // in C++ too this prints -2
printf("%d\n",(3,2,1)-(1,2,3)); // prints -2
printf("%d\n",("%d",3,2,1)-(1,2,3)); // prints -2
return 0;
}
By the output I am guessing its (1-3) = -2. But how from (3,2,1) value 1 is chosen, similarly from (1,2,3) value 3 is chosen? Am I right in what I am guessing?
Here, the comma operator and it's property is being used.
To elaborate, from C11, chapter §6.5.17, Comma operator
The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value
and, from C++11, chapter § 5.18,
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.
So, in case of a statement like
(3,2,1)-(1,2,3)
for the evaluation,
(3,2,1), 3 and 2 are (evaluated as a void expression and) discarded, 1 is the value.
(1,2,3), 1 and 2 are (evaluated as a void expression and) discarded, 3 is the value.
so, the statement reduces to 1 - 3 which is equal to -2.
Same way, you can use for more elements, also.
(3,2,1) means to calculate all the expressions and return last.
So, it does:
3 - nothing
2 - nothing
1 - return 1
And other:
1 - nothing
2 - nothing
3 - return 3
so your
cout << (3,2,1)-(1,2,3) << endl;
means:
cout << 1 - 3 << endl;
You have to consider the comma operator (,)
The comma operator (,) is used to separate two or more expressions
that are included where only one expression is expected. When the set
of expressions has to be evaluated for a value, only the right-most
expression is considered.
In your case:
(3,2,1) //evaluates to 1
(1,2,3) //evaluates to 3
source:
http://www.cplusplus.com/doc/tutorial/operators/
Comma operator always returns the last value i.e.
in your first cout it is 1-3=-2
next, in printf again it is 1-3=-3
finally in last printf, it is again 1-3=-2
Comma operator always solves all the left expressions(operands) and just returns the rightmost operand as result as rvalue.

Is comma operator free from side effect?

For example for such statement:
c += 2, c -= 1
Is it true that c += 2 will be always evaluated first, and c in second expression c-= 1 will always be updated value from expression c += 2?
Yes, it is guaranteed by the standard, as long as that comma is a non-overloaded comma operator. Quoting n3290 §5.18:
The comma operator groups left-to-right.
expression:
assignment-expression
expression , assignment-expression
A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded-
value expression (Clause 5)83. 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.
And the corresponding footnote:
83 However, an invocation of an overloaded comma operator is an ordinary function call; hence, the evaluations of its argument
expressions are unsequenced relative to one another (see 1.9).
So this holds only for the non-overloaded comma operator.
The , between arguments to a function are not comma operators. This rule does not apply there either.
For C++03, the situation is similar:
The comma operator groups left-to-right.
expression:
assignment-expression
expression , assignment-expression
A pair of expressions separated by a comma is evaluated left-to-right and the value of the left expression is
discarded. The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conver-
sions are not applied to the left expression. All side effects (1.9) of the left expression, except for the
destruction of temporaries (12.2), are performed before the evaluation of the right expression. The type and
value of the result are the type and value of the right operand; the result is an lvalue if its right operand is.
Restrictions are the same though: does not apply to overloaded comma operators, or function argument lists.
Yes, the comma operator guarantees that the statements are evaluated in left-to-right order, and the returned value is the evaluated rightmost statement.
Be aware, however, that the comma in some contexts is not the comma operator. For example, the above is not guaranteed for function argument lists.
Yes, in C++ the comma operator is a sequence point and those expression will be evaluated in the order they are written. See 5.18 in the current working draft:
[snip] is evaluated left-to-right. [snip]
I feel that your question is lacking some explanation as to what you mean by "side effects". Every statement in C++ is allowed to have a side effect and so is an overloaded comma operator.
Why is the statement you have written not valid in a function call?
It's all about sequence points. In C++ and C it is forbidden to modify a value twice inside between two sequence points. If your example truly uses operator, every self-assignment is inside its own sequence point. If you use it like this foo(c += 2, c -= 2) the order of evaluation is undefined. I'm actually unsure if the second case is undefined behaviour as I do not know if an argument list is one or many sequence points. I ought to ask a question about this.
It should be always evaluated from left to right, as this is the in the definition of the comma operator:
Link
You've got two questions.
The first question: "Is comma operator free from side effect?"
The answer to this is no. The comma operator naturally facilitates writing expressions with side effects, and deliberately writing expressions with side effects is what the operator is commonly used for. E.g., in while (cin >> str, str != "exit") the state of the input stream is changed, which is an intentional side effect.
But maybe you don't mean side-effect in the computer science sense, but in some ad hoc sense.
Your second question: "For example for such statement: c += 2, c -= 1 Is it true that c += 2 will be always evaluated first, and c in second expression c-= 1 will always be updated value from expression c += 2?"
The answer to this is yes in the case of a statement or expression, except when the comma operator is overloaded (very unusual). However, sequences like c += 2, c -= 1 can also occur in argument lists, in which case, what you've got is not an expression, and the comma is not a sequence operator, and the order of evaluation is not defined. In foo(c += 2, c -= 1) the comma is not a comma operator, but in foo((c += 2, c -= 1)) it is, so it may pay to pay attention to the parentheses in function calls.