I'm confused about direct assignment and ternary conditional operators precedence:
#include<stdio.h>
int main(void)
{
int j, k;
j = k = 0;
(1 ? j : k) = 1; // first
printf("%d %d\n", j, k);
j = k = 0;
1 ? j : k = 1; // second
printf("%d %d\n", j, k);
return 0;
}
I would expect the output to be:
1 0
1 0
But it happens to be:
1 0
0 0
Plus I get this warning:
main.cpp:20: warning: statement has no effect
which is about the line I commented as second.
Since the direct assignment operator has less precedence than the ternary conditional operator, I was expecting lines commented as first and second to be equivalent. But alas it is not the case.
I tried this with g++ --version (Ubuntu 4.4.3-4ubuntu5) 4.4.3
The operator precedence in the C/C++ language in not defined by a table or numbers, but by a grammar. Here is the grammar for conditional operator from C++0x draft chapter 5.16 Conditional operator [expr.cond]:
conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
The precedence table like this one is therefore correct when you use assignment on the left side of the doublecolon, but not when used on the right side. What is the reason for this asymmetry I have no idea. It may be a historical reason: in C the conditional result was not lvalue, therefore assigning something to it had no sense, and allowing assignment to be accepted without parentheses might seem smart at that time.
The second line is equivalent to:
1 ? (j) : (k = 1);
That's the same as:
j;
That's the same as:
;
The key is that the two operands of the ternary conditional operator can be expressions, so operator precedence isn't relevant here. It's simply that the second operand is the assignment expression k = 1.
(1 ? j : k) = 1;
is equivalent to,
if(true) j = 1;
else k = 1;
And,
1 ? j : k = 1;
is equivalent to,
if(true) j; // warning: statement has no effect
else k = 1;
In the second case,
1 ? j : k = 1;
is evaluated as:
(1) ? (j) : (k = 1);
and since one evaluates to true, the expression evaluates to j which does nothing.
Related
I'm confused about direct assignment and ternary conditional operators precedence:
#include<stdio.h>
int main(void)
{
int j, k;
j = k = 0;
(1 ? j : k) = 1; // first
printf("%d %d\n", j, k);
j = k = 0;
1 ? j : k = 1; // second
printf("%d %d\n", j, k);
return 0;
}
I would expect the output to be:
1 0
1 0
But it happens to be:
1 0
0 0
Plus I get this warning:
main.cpp:20: warning: statement has no effect
which is about the line I commented as second.
Since the direct assignment operator has less precedence than the ternary conditional operator, I was expecting lines commented as first and second to be equivalent. But alas it is not the case.
I tried this with g++ --version (Ubuntu 4.4.3-4ubuntu5) 4.4.3
The operator precedence in the C/C++ language in not defined by a table or numbers, but by a grammar. Here is the grammar for conditional operator from C++0x draft chapter 5.16 Conditional operator [expr.cond]:
conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
The precedence table like this one is therefore correct when you use assignment on the left side of the doublecolon, but not when used on the right side. What is the reason for this asymmetry I have no idea. It may be a historical reason: in C the conditional result was not lvalue, therefore assigning something to it had no sense, and allowing assignment to be accepted without parentheses might seem smart at that time.
The second line is equivalent to:
1 ? (j) : (k = 1);
That's the same as:
j;
That's the same as:
;
The key is that the two operands of the ternary conditional operator can be expressions, so operator precedence isn't relevant here. It's simply that the second operand is the assignment expression k = 1.
(1 ? j : k) = 1;
is equivalent to,
if(true) j = 1;
else k = 1;
And,
1 ? j : k = 1;
is equivalent to,
if(true) j; // warning: statement has no effect
else k = 1;
In the second case,
1 ? j : k = 1;
is evaluated as:
(1) ? (j) : (k = 1);
and since one evaluates to true, the expression evaluates to j which does nothing.
https://leetcode.com/problems/decode-ways/
my solution:
class Solution {
public:
int numDecodings(string s) {
vector<int> dp(s.size(),0);
for(int i=0;i<s.size();i++)
{
int x =0;
if(s[i]-'0'>0 && s[i]-'0'<=9)
{
x = (i>0)? dp[i-1]:1;
}
if(i!=0 && stoi(s.substr(i-1,2))<=26)
{
cout<<i<<" ";
x = x + (i>=2 )? dp[i-2]:1;
}
dp[i] =x;
}
return dp[s.size()-1];
}
};
Running this code gives this error
Line 924: Char 34: runtime error: addition of unsigned offset to 0x602000000010 overflowed to 0x60200000000c (stl_vector.h)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_vector.h:933:34
My question is does the conditional operator evaluate dp[i-2] in (i>=2 )? dp[i-2]:1; even if the condition doesn't satisfy? Replacing it with a normal if-else solved my problem.
This line:
x = x + (i>=2) ? dp[i-2] : 1;
is likely not doing what you intend. The ternary ?: has lower precedence than +, so the statement actually becomes:
x = (x + (i>=2)) ? dp[i-2] : 1;
which means you are checking the trueness of x + (i>=2) instead of just i>=2. This is why dp[i-2] can be evaluated even when i < 2, because the entire expression x + (i>=2) could still be true.
You can fix this by putting explicit parentheses yourself:
x = x + ((i>=2) ? dp[i-2] : 1);
or rewriting it like this:
x += i>=2 ? dp[i-2] : 1;
This line doesn't evaluate the way you think it does.
x = x + (i>=2 )? dp[i-2]:1;
Per this page, the addition operator has a higher precedence than the ternary operator. Placing the ternary expression in parentheses should provide the desired behavior.
x += ((i>=2 ) ? dp[i-2] : 1); gets the job done. Even though I changed the operator to remove the redundant x, the parentheses are still necessary.
Consider the code:
int i, j;
i = (i = 1, j = 3);
i++;
cout<<i<<" "<<j;
This printed 4 3 (c++14).
I read that the comma operator evaluates the expression on its left and returns the one on its right. Now if that is correct, I want to know what is the return value of j = 3? Is it the rvalue? Or a reference to the lvalue?
How does this actually work?
I want to know what is the return value of j = 3?
Assignment operations* return (or "evaluate to") a reference to the left-hand side of the operation, in this case j.
So i = (i = 1, j = 3); is identical to:
i = 1;
j = 3;
i = j;
*For built-in types that is. Custom operator= overloads may return whatever they want, although it's recommended to return a reference to *this as it is the expected behavior among C++ programmers.
To calculate (i=1, j=3), it calculates, from left to right, the expressions separated by comma, and returns the value of the last (rightmost) expression. So it calculates i=1 (i becomes 1), then it calculates j=3 (j becomes 3), then returns 3.
After calculating (i=1, j=3), which returned 3, it performs the assignment, which sets i to 3.
Then i++ is calculated, which sets i to 4.
Then i and j are printed.
The assignment operator returns an lvalue referring to the left operand. It groups right-to-left. ([expr.ass]). Note that saying returning a reference to the lvalue doesn't make sense - it either returns an lvalue or not.
The comma operator performs the value computations and side effects from the left operand, discards them, and then does the same for the right operand. ([expr.comma])
So refactoring the comma operator would produce the following equivalent code:
i = 1; // left operand, value discarded
i = j = 3; // right operand, value preserved
i++;
and then refactoring the compound assignment would produce the following still equivalent code:
i = 1;
j = 3; // rightmost assignment
i = j; // leftmost assignment
i++;
in Does the C/C++ ternary operator actually have the same precedence as assignment operators?
Luchian Grigore's answer says that cases like
a ? b : c = d
will always be inferred as
a ? b : ( c = d )
because both = and ?: associate right to left so
in c++
k = 21 > 3 ? j = 12 : j = 10;
and
k = 1 > 3 ? j = 12 : j = 10;
both are fine.
In C
k = 21 > 3 ? 12 : j = 10
returns error
invalid lvalue in assignment.
Shouldn't above be inferred as (and return no error)
k= 21 > 3 ? 12 : ( j = 10 )
I assume now it is being grouped as
k = ( 21 > 3 ? 12 : j ) = 10
which gives error since in C(not in C++) ternary operator cannot return lvalue.
Can anyone tell me exactly how operators are grouped in this case.
Your linked question's (Does the C/C++ ternary operator actually have the same precedence as assignment operators?) answer by #hvd shows the answer.
The C++ and C grammars for ?: are different.
In C++, the rightmost operand is allowed to be an assignment expression (so the compiler [greedily] treats the = are part of the ?:) while in C the rightmost operand is a conditional-expression instead. Thus in C as soon as the compiler hits the = the analysis of ?: is complete and it treats it as k = ( 21 > 3 ? 12 : j ) = 10.
k=21>3?12:(j=10) gets evaluated as
if ( 21 > 3 )
k = 12;
else
k = ( j = 10 );
Since 21>3 is true, the else condition does not get evaluated and j has undefined value (or whatever value it had prior to this statement).
I'm confused about direct assignment and ternary conditional operators precedence:
#include<stdio.h>
int main(void)
{
int j, k;
j = k = 0;
(1 ? j : k) = 1; // first
printf("%d %d\n", j, k);
j = k = 0;
1 ? j : k = 1; // second
printf("%d %d\n", j, k);
return 0;
}
I would expect the output to be:
1 0
1 0
But it happens to be:
1 0
0 0
Plus I get this warning:
main.cpp:20: warning: statement has no effect
which is about the line I commented as second.
Since the direct assignment operator has less precedence than the ternary conditional operator, I was expecting lines commented as first and second to be equivalent. But alas it is not the case.
I tried this with g++ --version (Ubuntu 4.4.3-4ubuntu5) 4.4.3
The operator precedence in the C/C++ language in not defined by a table or numbers, but by a grammar. Here is the grammar for conditional operator from C++0x draft chapter 5.16 Conditional operator [expr.cond]:
conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
The precedence table like this one is therefore correct when you use assignment on the left side of the doublecolon, but not when used on the right side. What is the reason for this asymmetry I have no idea. It may be a historical reason: in C the conditional result was not lvalue, therefore assigning something to it had no sense, and allowing assignment to be accepted without parentheses might seem smart at that time.
The second line is equivalent to:
1 ? (j) : (k = 1);
That's the same as:
j;
That's the same as:
;
The key is that the two operands of the ternary conditional operator can be expressions, so operator precedence isn't relevant here. It's simply that the second operand is the assignment expression k = 1.
(1 ? j : k) = 1;
is equivalent to,
if(true) j = 1;
else k = 1;
And,
1 ? j : k = 1;
is equivalent to,
if(true) j; // warning: statement has no effect
else k = 1;
In the second case,
1 ? j : k = 1;
is evaluated as:
(1) ? (j) : (k = 1);
and since one evaluates to true, the expression evaluates to j which does nothing.