Conditional operator "?:" in C++ - c++

Why this statement :
int a = 7, b = 8, c = 0;
c = b > a? a > b? a++: b++: a++ ? b++:a--;
cout << c;
is not equal to :
int a = 7, b = 8, c = 0;
c = (b > a? (a > b? a++: b++): a++)? b++: a--;
cout << c;
and is equal to :
int a = 7, b = 8, c = 0;
c = b > a? (a > b? a++: b++): (a++? b++: a--);
cout << c;
Please give me some reason. Why ?

Operator precedence and associativity
Table of operator precedence and associativity for C++

Just put it on multiple lines to see the differences :
c = b>a // true
? a>b // false
? a++
: b++ // b is incremted = 9; c = 8 (post increment)
: a++
? b++
: a--;
is not equal to :
c = ( b>a // true
? ( a>b // false
? a++
: b++ ) // b is incremted = 9
: a++ ) // a = 7 (= 8 after post increment), thus true
? b++ // ... b is incremented = 10, c = 9 (post increment)
: a--;
and is equal to :
c = b>a // true
? ( a>b // false
? a++
: b++ ) // b is incremnted = 9, c = 8 (post increment)
: ( a++
? b++
: a-- );

Also, please note that these (horrible) expressions are deterministic only because the ?: operator is used. This operator is one of the very few operators in the C language where the order of evaluation is actually specified. Had you written some other abomination like i++ + ++i; then the compiler could have evaluated the left operand or the right operand first, which it picks is not defined in the C language.
As a rule of thumb, never use the ++ operator as part of an expression with other operators. Only use it on a line of its own (or as loop iterator). Because, against mainstream belief, there is actually never a reason to use it together with other operators.

Related

variable value, after ternary operator

I have these lines of code:
int a = 10, b = 1;
a = --b ? b : (b = -99);
cout << "a= " << a << "b= " <<b<< endl;
the output gives me b=-99 as a is not equal to 0(which makes senses) but it also changes the value of a to a=-99 how?
Your code is the equivalent of:
int a = 10, b = 1;
b -= 1; // b == 0
int x;
if (b != 0) x = b;
else x = b = -99;
a = x;
// at this point a and b have the same value
The ternary operator works as follows:
if (--b != 0) { // b is not 0 means true
a = b;
} else { // b is 0 means false
a = (b = -99);
}
You assign the value to a, so --b is 0 which is considered as false. Then you assign to b value -99 and afterward, you assign b to a. So, both variables have their values -99 in the end. Hope it will help you.
According to ternary operator, The first argument is a comparison argument(condition), the second is the result upon a true comparison, and the third is the result upon a false comparison.
So In Your case, the condition is not True, So the false statement get executed.
so now b has -99.
In c, c++, java we've seen, assigns the value of the variable
a = b = -99
In this, the both a & b gets the same value. Like this, ternary operator also assigning the value of the variable from false statement .
(a = (b = -99 ))
I think what is confusing you here is that, in C, an expression (such as b = -99) has both consequences and a value. The consequence of b = -99 is that b is assigned the value of -99; but note also that the value of this expression is -99.
Thus, in a ternary expression, which takes the general form:
lhs = test ? v_if_true : v_if_false;
the expression test is first evaluated and lhs is assigned either v_if_true (if test evaluates to non-zero) or v_if_false (if test evaluates to zero).
In your case, test is --b. The consequence of this expression is that the value of b is decreased by one, and the value of the expression is the resulting (modified) value of b (which will be zero in your code).
So, your ternary expression assigns to a the value of the v_if_false expression which is b = -99 (the brackets you give add clarity to the expression, but don't change its evaluation). So, as mentioned above, this expression (as well as modifying b) also has a calculated value of -99, which is then given to a.
If you wanted to leave a unchanged in the case when the v_if_false expression is executed, then you could do this using the comma operator, as follows (though I would not recommend using such code):
a = --b ? b : ((b = -99), a); // If --b == 0, this becomes a = a
This works because the value of an expression containing the comma operator is the value of the sub-expression after (to the right of) the comma.

Evaluation of logical condition in ternary operator

I do not know whether parens are required before the ternary operator.
Example:
int a,b,d,e,f; // Some numbers
int l = ( a > b || d < e ) ? a : d;
is surely fine, if a>b or d<e then l = a else l = d.
I am not sure if instead
int l = a > b || d < e ? a : d;
is equally valid, and what about longer statements?
int l = ( a > b || d ) && e > f ? a : d;
I guess that my question is: the ternary operator always treat whatever comes before him as a logical expression and evaluates it, and therefore there is no need for parens before it?
Your first example is correct.
And the second statement is equally valid to the first one.
Your second example reads as follows:
(...) have highest precedence and > and < have higher precedence than && which has higher precedence than || which has higher precedence than ?:.
So
if the result of a > b || d (d is converted to 1 if different than 0) is true
and
if the result of e > f is true
then
l=a
otherwise l=b.

Why does the expression a = a + b - ( b = a ) give a sequence point warning in c++?

Following is the test code:
int main()
{
int a = 3;
int b = 4;
a = a + b - (b = a);
cout << "a :" << a << " " << "b :" << b << "\n";
return 0;
}
Compiling this gives the following warning:
> $ g++ -Wall -o test test.cpp test.cpp: In function ‘int main()’:
> test.cpp:11:21: warning: operation on ‘b’ may be undefined
> [-Wsequence-point]
Why can the operation be undefined?
According to my understanding, first the subexpression (b = a) should be evaluated because of higher precedence of (), thus setting b = a. Then, since '+' and '-' have same precedence, the expression would be evaluated left-associatively. Thus, a + b should be evaluated next, and finally the result of (b = a) should be subtracted from a + b. I can't see any sequence-point rule being violated here.
There is a difference between an expression being evaluated and completing its side effects.
The b = a assignment expression will be evaluated ahead of subtraction due to higher precedence of the parentheses. It will provide the value of a as the result of the evaluation. The writing of that value into b, however, may not complete until the next sequence point, which in this case is the end of the full expression. The end result of the overall expression is therefore undefined, because the subtraction may take the value of b before or after the assignment.
In C++, subexpressions in arithmetic expressions do not have temporal ordering.
a = x + y;
Is x evaluated first, or y? The compiler can choose either, or it can choose something completely different. The order of evaluation is not the same thing as operator precedence: operator precedence is strictly defined, and order of evaluation is only defined to the granularity that your program has sequence points.
In fact, on some architectures it is possible to emit code that evaluates both x and y at the same time -- for example, VLIW architectures.
To solve it separate them in two different statements.
PS: Don't forget that humans may make mistakes performing arithmetic operations. Therefore is better to make the operations clearer by separating them in different statements. I hope I helped.
int main()
{
int a = 3;
int b = 4;
/* Two different Statements*/
b = a;
/* or a = a + b - a */
a = a + b - b;
cout<<"a :"<<a<<" "<<"b :"<<b<<"\n";
return 0;
}
a = b + a - a;
is just written as
a = b + a - (b = a)------>> (exp 1)
The following three results same as (exp 1)
a = (b + a - (b = a));
a = ((b + a) - (b = a));
a = (b + a) - (b = a);
Observations
+, - operators has got same precedence and also left to right associativity
Hence 'b+a' gets executed first and then 'a' value gets assigned to 'b' before subtraction
Now observe the following
When a = 10 and b = 20;
a = (b = a) - b + a; =======> a = 10; b = 10
a = ((b = a) - b + a); =======> a = 10; b = 10
a = ((b = a) - (b + a)); =======> a = -10; b = 10
From the above expressions its clear that even if innermost parenthesis gets executed first the associativity is followed first and then the precedence
Note:
To avoid confusion between the precedence of outer and inner parenthesis
Consider the following expression
a = (b + a - (b = a)) =====> Actual Result => a = 20, b = 10;
would have been a = 10, b = 10; (if precedence is primary when compared to associativity)
Thus by the above example we can say that associativity is primary when compared to precedence

ternary and assignment operator precedence

On MSVC v9.0, if I do this:
int myvalue;
myvalue = true ? 1 : 0;
then it seems that ?: is evaluated before '='. Is this a guarantee? I am using this table as a reference:
http://en.cppreference.com/w/cpp/language/operator_precedence
However, both operators are in the same row, so I'm not sure if they are evaluated in the order I expect or if this is guaranteed by the standard. Can anyone clarify this?
In this statement
int myvalue = true ? 1 : 0;
there's only one operator, the ternary operator. There's no assignment operator here, so precedence doesn't matter.
Don't confuse initialization with assignment:
int myvalue;
myvalue = true ? 1 : 0; // now priorities are important
From your link:
Operators that are in the same cell (there may be several rows of operators listed in a cell) are evaluated with the same precedence, in the given direction. For example, the expression a=b=c is parsed as a=(b=c), and not as (a=b)=c because of right-to-left associativity.
Since both = and ?: are in the same cell and have right-to-left associativity, the ternary is guaranteed to evaluate first.
They are evaluated right to left, as it written in the table you linked. It is equivalent of this:
int myvalue = (true ? 1 : 0);
Right-to-left:
int myValue1 = 20, myValue2 = 30;
myValue1 = true ? 1 : 0; // which is the same as:
myValue1 = ((true) ? (1) : (0));
// myValue == 1 && myValue2 == 30
true ? myValue1 : myValue2 = 5; // which is the same as:
(true) ? (myValue1) : ((myValue2) = (5));
// myValue == 1 && myValue2 == 30
false ? myValue1 : myValue2 = 5; // which is the same as:
(false) ? (myValue1) : ((myValue2) = (5));
// myValue == 1 && myValue2 == 5
This is guaranteed in the C++ language

question about ? and : in c++

Why this statement :
int a = 7, b = 8, c = 0;
c = b>a?a>b?a++:b++:a++?b++:a--;
cout << c;
is not equal to :
int a = 7, b = 8, c = 0;
c = (b>a?(a>b?a++:b++):a++)?b++:a--;
cout << c;
and is equal to :
int a = 7, b = 8, c = 0;
c = b>a?(a>b?a++:b++):(a++?b++:a--);
cout << c;
Please give me some reason. Why ?
Because ? : is right-to-left associative. It's defined like that in the language.
I believe #sth has provided the correct answer, however, I think #Skilldrick got it right on the comments - why the hell would you ever write something like that.
As well as the precedence issue, you really need to be careful when incrementing the same variables in a single statement. There may or may not be sequence points in the statement, and therefore the order of evaluation of the increments might not be guaranteed. You could end up with different results with different compilers or even different optimization settings on the same compiler.
The operators &&, ||, and ?: perform flow control within expressions. ?: behaves like an if-else statement.
c = b>a?a>b?a++:b++:a++?b++:a--;
if ( b>a )
if ( a>b )
a ++;
else
b ++;
else if ( a ++ )
b ++;
else
a --;
b>a? (
a>b ?
a ++
:
b ++
) : ( a ++ ?
b ++
:
a --
)
The associativity is necessary to have behavior like if … else if … else.
Sometimes I use an expression similar to yours for lexicographic sequence comparision:
operator< ()( arr &l, arr &r ) {
return l[0] < r[0]? true
: r[0] < l[0]? false
: l[1] < r[1]? true
: r[1] < l[1]? false
: l[2] < r[2];
}