Ternary and comma operator [duplicate] - c++

This question already has answers here:
What's the precedence of comma operator inside conditional operator in C++?
(3 answers)
Closed 6 years ago.
int a,b;
a = 1 ? 1,2 : 3,4; // a = 2
b = 0 ? 1,2 : 3,4; // b = 3
Comma operator returns always the right side of comma, but if we make an assignment to variable it returns left except the case when we use ().
So how the hell the first expression gives the 2.
I see it as a = 1,2 so it should be 1 but actually a=2.
Why?

Due to operator precedence (comma operator having least precedence), your code actually looks like
int a,b;
(a = 1 ? (1,2) : 3),4; // a = 2
(b = 0 ? (1,2) : 3),4; // b = 3
So, as per the ternary condition rule, quoting C11, chapter §6.5.15
The first operand is evaluated; there is a sequence point between its evaluation and the
evaluation of the second or third operand (whichever is evaluated). The second operand
is evaluated only if the first compares unequal to 0; the third operand is evaluated only if
the first compares equal to 0; the result is the value of the second or third operand
(whichever is evaluated), converted to the type described below. 110)
[...]
110) A conditional expression does not yield an lvalue.
For first case, the second operand is evaluated and returned.
For second case, the third operand is evaluated and returned.

Related

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.

C/C++ How does compiler separate tokens according to operator's precedence and associativity?

Consider the following codes:
int a = 3;
int b = 0;
b = a > 0 ? ++b, ++a : --a, b = 0;
After execution, I get the value of b to become 0 and the value of a to become 4.
That means the result of condition expression, a > 0 is evaluated as true and the expression a++ has been executed, while the expression b = 0 after , hast been executed ,too. In other words, the expression b = 0 is not an operand of the ternary operator, while ++b is. Otherwise, b = 0 won't be executed since the condition expression isn't evaluated as false.
My question is "according to what rule does the compiler kick b = 0 out of the ternary operator's operand?"
The operators in the third statement includes: ++ and --, which have the highest precedence, >, which has the second largest precedence, ? : and =, which have the third largest precedence and , with the lowest precedence. I know that operators with higher precedence should determine their operands earlier so that ++,--, and > are handled first. Then the statement is equivalently:
b = (a > 0) ? (++b), (++a) : (--a), b = 0;
Now, it's = and ?:'s turn to be handled. The associativity of = and ?: is right-to-left, so I consider the compiler will parse the statement from the right end.The first operator met is = and so b = 0 is grouped together. The second met operator is ,. Since it's precedence is lower then the current operators being analyzed, I assume the compiler will just skip it. Then the compiler met :, which is a part of ternary operator, so it keeps parsing.(Actually I don't know how the compiler can know that : is a part of ?: before parsing the whole ternary operator) Problem comes here. The next operator met by the compiler is , but the compiler haven't finished determining the operands of ?: yet. The , has lower priority than ?:. Theoretically it should be skipped; surprisingly, in practical test, the (++b) and (++a) have been concatenated by the , operator at this time and both are considered as the operand of ?:. That makes me confused. Why does the last , is ignored and doesn't included in the operand of ?: while the previous , in statement is kept in the operand of ternary operator?
May someone clarify the concepts of precedence and associativity with this example? I'm really confused about the executing result when first taking a sight of this piece of codes. I had thought that the expression b=0 is also a part of the ternary operator's operand; therefore b = 0 will only be executed if a > 0 is false.
Thanks in advance.
Precedence and associativity are different concepts, but technically the C and C++ standard specifies none. Instead they give the grammar rules to deduce the structure of the expression.
The relevant rules are:
conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
expression:
assignment-expression
expression , assignment-expression
primary-expression:
( expression )
postfix-expression:
primary-expression
...
And so on...
The idea is that each type of expression can generate a composite expresion or another type of expression of lower precedence. You can only go up to the root expression by using parenthesis.
With that in mind, note that the conditional-expression that uses the ?: actually has different types of expressions in each of the three subexpressions. The middle one is expression so it will accept any kind of expression, even with , or = (no ambiguity here because of the ending :).
But note that the last one is assignment-expression, that is any kind of expression except the one with ,. If you want to use that, you will have to enclose it with () creating a primary-expression instead.
Bonus explanation: the first expression is logical-or-expression, and if you look carefully to the grammar you'll see that it excludes assignment operators, the conditional operator and the comma operator.
So your expression:
b = a > 0 ? ++b, ++a : --a, b = 0
Is actually a expression comma assignment-expression, where the first expression is b = a > 0 ? ++b, ++a : --a and the second assignment-expression is b = 0.
And so on...
Your expression is evaluated as (b = ((a > 0) ? (++b, ++a) : (--a))), (b = 0);.
As you say the ?: has higher precedence than the comma operator, so the b=0 does not belong to the ternary conditional. The difference for the left and the right part of the ternary operator is, that on the left side the compiler tries to evaluate the complete string ++b, ++a as an expression (knowing that the part between ? and : must be an expression, while on the right side the compiler tries to parse an expression as far as it can. And precedence of operators says the compiler must stop at the ,. On the left side the compiler does not stop on the , because this is a legal part of the expression.

Why does putting parentheses around a list of comma separated values change the assignment? [duplicate]

This question already has answers here:
What does a comma separated list of values, enclosed in parenthesis mean in C? a = (1, 2, 3); [duplicate]
(6 answers)
How does the Comma Operator work
(9 answers)
Closed 9 years ago.
Please consider following code,
int i;
i = 1,2,3,4,5;
printf("First time i = %d\n",i);
i = (1,2,3,4,5);
printf("Second time i = %d\n",i);
Output:
First time i = 1
Second time i = 5
Why do the parentheses make the comma operator take last value and without parentheses it takes first value?
Thanks in advance.
First one is equivalent to (i = 1),2,3,4,5; which means the commas have no effect. When used with parentheses it returns the last value in the "comma delimited list"
This is all due to operator precedence, which you can view a table about here
This is due to the operator precedence and the order of evaluation. = binds harder than , and from that we can figure out that the below two expressions are the same:
i = 1,2,3,4,5 /* <- same as -> */ (i = 1),(2),(3),(4),(5)
side-note: the comma operator is the "weakest" operator of them all
Why does the comma operator yield the last value of our list?
To put it simple this operator evaluate the first operand only to discard it and move on to the next one, it binds left-to-right which means that it will start from the left, and continue walking towards the right.
Where can I read more about this topic?
cppreference.com - C++ Operator Precedence
swansontec.com - C Language Operator Precedence
Assignment has higher precedence than comma , hence the result you get in the first case. You can find the entire operator precedence table here .
Why parenthesis makes comma operator to take last value and without parenthesis it takes first value?
Because parenthesis is used to override the precedence. The first case is implicitly equivalent to :
(i = 1),2,3,4,5;
Comma evaluates from left to right and the rightmost value is the value of the entire expression. Read the documentation here.
The comma operator has left-to-right associativity. Two expressions separated by a comma are evaluated left to right. The left operand is always evaluated, and all side effects are completed before the right operand is evaluated.
Because = has a higher precedence than , (which has the lowest), the first is the same as
(i = 1),2,3,4,5;
which assigns 1 to i (i = 1) then evaluating the expressions 2, 3, 4, and 5 through the comma operators (the whole expression actually results in 5, which is not used). In the second one,
(1,2,3,4,5)
is parenthesized, therefore it will be first evaluated before =. It results in 5 (the right-most expression; this is the behavior of the comma operator) which is then assigned to i.
i = (1,2,3,4,5);
| |
\---------\--- results in 5 then is assigned to i
See operator precedence Wikipedia article.

Something we found when using comma in condition ternary operator? [duplicate]

This question already has answers here:
What's the precedence of comma operator inside conditional operator in C++?
(3 answers)
Closed 9 years ago.
Well, I had a question about comma in ternary operator.
Cut the crap, the code is below:
void test_comma_in_condition(void)
{
int ia, ib, ic;
ia = ib = ic = 0;
bool condition=true;
cout<<"Original:"<<endl;
cout<<"ia: "<<ia<<endl;
cout<<"ib: "<<ib<<endl;
condition?(ia=1, ib=2):(ia=11, ib=12);
cout<<"After:"<<endl;
cout<<"ia: "<<ia<<endl;
cout<<"ib: "<<ib<<endl;
ia = ib = ic = 0;
condition?ia=1, ib=2, ic=3:ib=22,ia=21, ic=23;
cout<<"The operation must be bracketed, or you'll see..."<<endl;
cout<<"ia: "<<ia<<endl;
cout<<"ib: "<<ib<<endl;
cout<<"ic: "<<ic<<endl;
condition?ia=1, ib=2, ic=3:ia=21, ib=22, ic=23;
cout<<"The operation must be bracketed, or you'll see..."<<endl;
cout<<"ia: "<<ia<<endl;
cout<<"ib: "<<ib<<endl;
cout<<"ic: "<<ic<<endl;
return;
}
The output will be like:
Original:
ia: 0
ib: 0
After:
ia: 1
ib: 2
The operation must be bracketed, or you'll see...
ia: 21
ib: 2
ic: 23
The operation must be bracketed, or you'll see...
ia: 1
ib: 22
ic: 23
Is this legal?
This is a matter of operator precedence. Your expression:
condition?ia=1, ib=2, ic=3:ib=22,ia=21, ic=23;
is understood by the compiler as:
(condition?(ia=1, ib=2, ic=3):(ib=22)),ia=21, ic=23;
At this point you should be able to see why you get the program output.
Yes, the relevant grammar for a conditional expression is:
logical-or-expression ? expression : assignment-expression
for assignment expressions (which can also be a conditional-expression or a throw-expression):
logical-or-expression assignment-operator assignment-expression
and for an expression with a comma operator (an assignment-expression can also be an expression):
expression , assignment-expression
This means that the construct a ? b : c, d cannot be parsed as equivalent to a ? b : (c, d) because c, d is not an assignment-expression but must be parsed as equivalent to (a ? b : c), d.
There is no undefined behaviour in condition ? ia=1,ib=2,ic=3 : ia=21, ib=22, ic=23; because evaluation of condition is sequenced before the evaluation of either the second or third operands of ?: and in every sub-expression containing a comma operator the evaluation of the first operand of the comma operator is sequenced before the evaluation of the second operand.
It's legal, but stupid not very useful to write code like that.
The code
condition?ia=1, ib=2, ic=3:ia=21, ib=22, ic=23;
is equivalent to
condition?(ia=1, ib=2, ic=3):ia=21;
ib=22;
ic=23;
just harder to read.
The problem is that the comma operator has the lowest precedence there is. Thanks to that, the else part of the conditional operator is just the first assignment, after that the comma operator kicks in and the other two statements will be executed just aswell.

How does this piece of code work?

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.