Ternary operator in C vs C++ [duplicate] - c++

This question already has answers here:
Errors using ternary operator in c
(5 answers)
Closed 8 years ago.
There are a lot of differences between C and C++ and came to stuck on one of them
The same code gives an error in C while just executes fine in C++
Please explain the reason
int main(void)
{
int a=10,b;
a>=5?b=100:b=200;
}
The above code gives an error in C stating lvalue required while the same code compiles fine in C++

Have a look at the operator precedence.
Without an explicit () your code behaves like
( a >= 5 ? b = 100 : b ) = 200;
The result of a ?: expression is not a modifiable lvalue [#] and hence we cannot assign any values to it.
Also, worthy to mention, as per the c syntax rule,
assignment is never allowed to appear on the right hand side of a conditional operator
Relared Reference : C precedence table.
OTOH, In case of c++, well,
the conditional operator has the same precedence as assignment.
and are grouped right-to-left, essentially making your code behave like
a >= 5 ? (b = 100) : ( b = 200 );
So, your code works fine in case of c++
[ # ] -- As per chapter 6.5.15, footnote (12), C99 standard,
A conditional expression does not yield an lvalue.

Because C and C++ aren't the same language, and you are ignoring the assignment implied by the ternary. I think you wanted
b = a>=5?100:200;
which should work in both C and C++.

In C you can fix it with placing the expression within Parentheses so that while evaluating the assignment becomes valid.
int main(void)
{
int a=10,b;
a>=5?(b=100):(b=200);
}
The error is because you don't care about the operator precedence and order of evaluation.

Related

What's this =! operator? [duplicate]

This question already has answers here:
What does the "=!" operator do? [closed]
(6 answers)
Closed 9 years ago.
I was surprised by this code:
if (a =! b) { // let it be on false
...
}
But a is never assigned by a value. What's this operator about?
That's two operators, = and !, not one. It might be an obfuscated way of writing
a = !b;
if (a) {
// whatever
}
setting a to the logical inverse of b, and testing whether the result is true (or, equivalently, whether b was false).
Or it might be a mistyping of a != b.
Long ago, when dinosaurs roamed the earth and C ran on 5th edition UNIX on PDP-11s, =! was the 'not equals' operator. This usage was deprecated by the creation of Standard C, so now it means 'assign the logical inverse', as in a = !b. This is a good argument for always surrounding binary operators with spaces, just to make it clear to the humans reading the code what the compiler is thinking.
I'm a bit surprised nobody else mentioned this, but then again I may be the only SO user to have ever touched a C compiler that old.
a is assigned the boolean negation of b in that line. It is just a misformatted
if( a = !b ) {
... and an evil hidden assignment inside a condition.
a =! b
is just a funny way of putting
a = !b
i.e. the assignment of not b to a.
The value of the expression is a after the assignment.
With the code below you can see that the value of the expression a = !b is !false (i.e. true), and you can then see the assignment has taken place by checking the value of a, which is also true.
#include <iostream>
int main()
{
bool a = false;
bool b = false;
if(a)
printf("a is true!\n");
else
printf("a is false!\n");
if(a = !b)
printf("expression is true!\n");
else
printf("expression is false!\n");
if(a)
printf("a is true!\n");
else
printf("a is false!\n");
}
Result:
a is false!
expression is true!
a is true!
Operators in C++
According to C/C++ operators list there is no operator such as =!. However, there is an operator != (Not equal to, Comparison operators/relational operator)
There are two possibilities.
It could be typo mistake as I've noticed that =! operators is in if statement and someone is trying to type != instead of =! because != is the comparison operator which returns true or false.
Possibly, the developer was trying to assign the boolean negation of b to a and he/she has done a typo mistake and forgot to put a space after equal sign. This is how the compiler interprets it, anyways.
According to Operator precedence in c++:
Operator Logical NOT (!) precedence is 3 and Associativity is Right-to-left
Operator Direct assignment (=) precedence is 16 and Associativity is Right-to-left
They are two different operators: the = (assignment) operator together with the ! operator. It can basically be translated to an assignment of a to the negated value of b.
if (a = !b)
But, what the user, probably, meant to write was the != operator:
if (a != b)
That is not a single operator, it is however, a great way to obfuscate code.
If it were written a=!b instead, the white space might not lead you to believe that it was a single operator.
Compilers have warnings for assignment in a conditional expression unless you wrap the entire statement in a set of parenthesis, and this is a perfect example of when this warning would be useful.
Both of these statements are functionally identical, but one generates a warning and the other does not:
if (a =! b) // Generates a warning with `-Wparentheses` (gcc)
if ((a =! b)) // No such warning
-Wparentheses
Warn if parentheses are omitted in certain contexts, such as when there is an assignment in a context where a truth value is expected, or when operators are nested whose precedence people often get confused about.
This, of course, assumes that you are a responsible programmer and actually read the warnings your compiler spits out.
Using white space in a more reasonable way, the statement is actually:
if (a = !b) // Assign A the value of (logical) NOT B and then test the truth
The compiler warning mentioned above is actually useful in the case where the person who wrote this code accidentally transposed ! and =. However, from the cryptic inline comments in your original question, a = !b is probably the author's intention.
C++ does not have an =! operator, which immediately means that this is an = operator followed by a ! operator. So, you simply have a = !b in the if condition.
This is all about clarity of code:
It should be written as: if (a = !b)
if (a = !b) is the same as saying if a is assigned to !b. So there are technically 2 separate operators being used, = which is an assignment operation, and ! which is a logical expression.
Just put a space between = and ! it solves this confusion.
There could be three reasons for this:
It could be a mistyping of the != operator, meaning not equal to. Example:
if (a != b) {
// a is not equal to b
}
It could be a mistyping a == !b, meaning a is equal to not b, which would most commonly be used with booleans. Example:
if (a == !b) {
// The boolean a is equal to not b (a is not equal to b)
}
It could be trying to assign a to the inverse of b. Example:
bool a = !b; // Sets a to the opposite of b
I think this is one of the writing or printing mistake. Because if we can not compile this code as it holds a compiletime error. And here this is inside if clause, the return type must be boolean. So how can it possible. The answer is simply a mistake or as Mike said obfuscated way of writing.
And only possible if both variables a and b are boolean which will be compiled as a is equal to (not)b i.e (a = !b) .
This can be taken as a is assigned to !b.
I am trying to answer your question and, in agreement with Mike's answer, I am just adding up.
You can also understand it by a=!!b.
The code a=!b returns 0 to a and a=!!b returns 1 to a.
The =! is not a single operator but the mix of these two.
These types of question are asked to misguide students to check their coding skills.

What is the "?" and ":" sequence actually called? [duplicate]

This question already has answers here:
What does the question mark character ('?') mean in C++?
(8 answers)
Closed 9 years ago.
This may be a bonehead question, but I cannot figure out what the ? exp : other_exp sequence is called.
Example:
int result = (true) ? 1 : 0;
I've tried using the Google machine, but it's hard to Googilize for something without knowing what it's called.
Thanks!
It is called the the conditional operator or alternativly the ternary operator as it a ternary operator (an operator which takes 3 operands (arguments)), and as it's usually the only operator, that does this.
It is also know as the inline if (iif), the ternary if or the question-mark-operator.
It is actualy a rather useful feature, as they are expressions, rather than statements, and can therefore be used, for instance in constexpr functions, assigments and such.
The C++ Syntax is;
logical-or-expression ? expression : assignment-expression
It's used as;
condition ? condition_is_true_expression : condition_is_false_expression
That is, if condition evaluates to true, the expression evaluates to condition_is_true_expression otherwise the expression evaluates to condition_is_false_expression.
So in your case, result would always be assigned the value 1.
Note 1; A common mistake that one makes while working with the conditional operator, is to forget that it has a fairly low operator precedence.
Note 2; Some functional languages doesn't provide this operator, as they have expression 'if...else' constructs, such as OCaml;
let value = if b then 1 else 2
Note 3; A funny use case, which is perfectly valid is using the conditional operator, to decide, which of two variable to assign a value to.
(condition ? x : y) = 1;
Notice the parentheses are necessary, as this is really what you get without them;
condition ? x : (y = 1);
They are called shorthand if-else or ternary operators.
See this article for more information.

Why the Standard C++ Grammar for Assignment Expression Looks so Weird

From the C++ standard, the grammar for an assignment expression is like this:
assignment-expression:
conditional-expression
logical-or-expression assignment-operator assignment-expression
throw-expression
assignment-operator: one of
= *= /= %= += -= >>= <<= &= ^= |=
Notice that the left hand side of the "assignment-operator" is "logical-or-expression" i.e. something like (4 || localvar1) = 5; is a valid assignment expression according to the grammar. This doesn't make sense to me. Why they choose a "logical-or-expression" instead of, say, an identifier or id_expression?
The grammar is a bit complex, but if you continue unrolling with the previous definitions you will see that assignment expressions are very generic and allow for mostly anything. While the snippet from the standard that you quote focuses on logical-or-expression, if you keep unrolling the definition of that you will find that both the left hand side and right hand side of an assignment can be almost any subexpression (although not literally any).
The reason as pointed out before is that assignment can be applied to any lvalue expression of enum or fundamental type or rvalue expression of a class type (where operator= is always a member). Many expressions, in a language that allows for operator overloading and that does not define what the type returned from the operator is, can potentially fulfill the needs of assignment, and the grammar must allow all of those uses.
Different rules in the standard will later limit which of the possible expressions that can be generated from the grammar are actually valid or not.
Your particular statement, (4 || localvar1) = 5; is invalid (unless operator|| is overloaded), because you can't assign 5 to 4 (4 is an r-value). You must have an l-value (something that can be assigned to) on the left, such as a reference returned by a function.
For example, say you have some function int& get_my_int() that returns the reference to an integer. Then, you can do this:
`get_my_int() = 5;`
This will set the integer returned by get_my_int() to 5.
Just like in your first post, this MUST be a reference to an integer (and not a value); otherwise, the above statement wouldn't compile.
There are actually two interesting things about the C++ grammar for assignment statements, neither of which have to do with the validity of:
(4 || localvar1) = 5;
That expression is syntactically valid (up to type-checking) because of the parentheses. Any parenthesized expression of reference type is syntactically correct on the left-hand-side of an assignment operator. (And, as has been pointed out, almost any expression which involves a user type or function can be of reference type, as a result of operator overloading.)
What's more interesting about the grammar is that it establishes the left precedence of assignment operators as being lower than almost all other operators, including logical-or, so that the above expression is semantically equivalent to
4 || localvar1 = 5;
even though many readers would interpret the above as 4 || (localvar1 = 5) (which would have been totally correct assuming that localvar1 is of a type which can be assigned to by an int, even though said assignment will never happen -- unless, of course, || is overloaded in this context).
So what has a lower precedence on the left hand side of an assignment operator? As I said, very little, but one important exception is ?::
// Replace the larger of a and b with c
a > b ? a = c : b = c;
is valid and conveniently parenthesis-less. (Many style guides insist on redundant parentheses here, but I personally rather like the unparenthesized version.) This is not the same as right-hand precedence, so that the following also works without parentheses:
// Replace c with the larger of a and b
c = a > b ? a : b;
The only other operators which bind less tightly on the left of an assignment operator than the assignment operator are the , operator and another assignment operator. (In other words, assignment is right-associative unlike almost all other binary operators.) Neither of these are surprising -- in fact, they are so necessary that it's easy to miss how important it is to design a grammar in this way. Consider the following unremarkable for clause:
for (first = p = vec.begin(), last = vec.end(); p < last; ++p)
Here the , is a comma operator, and it clearly needs to bind less tightly than either of the assignments which surround it. (C and C++ are only exceptional in this syntax by having a comma operator; in most languages, , is not considered an operator.) Also, it would obviously be undesirable for the first assignment expression to be parsed as (first = p) = vec.begin().
The fact that assignment operators associate to the right is unremarkable, but it's worth noting for one historical curiosity. When Bjarne Stroustrup was looking around for operators to overload for I/O streams, he settled on << and >> because, although an assignment operator might have been more natural [1], assignment binds to the right, and a streaming operator must bind to the left (std::cout << a << b must be (std::cout << a) << b). However, since << binds much more tightly than assignment, there are a number of gotchas when using the streaming operators. (The one which most recently caught me is that shift binds more tightly than the bitwise operators.)
[Note 1]: I don't have a citation for this, but I remember reading it many years ago in The C++ Programming Language. As I recall, there was not a consensus about assignment operators being natural, but it seems more natural than overloading shift operators to be something completely different from their normal semantics.

Ternary operator why c++ gives rvalue but lvalue in c [duplicate]

I read somewhere that the ?: operator in C is slightly different in C++, that there's some source code that works differently in both languages. Unfortunately, I can't find the text anywhere. Does anyone know what this difference is?
The conditional operator in C++ can return an lvalue, whereas C does not allow for similar functionality. Hence, the following is legal in C++:
(true ? a : b) = 1;
To replicate this in C, you would have to resort to if/else, or deal with references directly:
*(true ? &a : &b) = 1;
Also in C++, ?: and = operators have equal precedence and group right-to-left, such that:
(true ? a = 1 : b = 2);
is valid C++ code, but will throw an error in C without parentheses around the last expression:
(true ? a = 1 : (b = 2));
The principal practical difference is that in C, evaluation of ?: can never result in a l-value where as in C++ it can.
There are other differences in its definition which have few practical consequences. In C++ the first operand is converted to a bool, in C it is compared against 0. This is analagous to the difference in definition of ==, !=, etc. between C and C++.
There are also more complex rules in C++ for deducing the type of a ?: expression based on the types of the 2nd and 3rd operands. This reflects the possibility of user-defined implicit conversions in C++.
Example code. Valid C++; invalid C.
extern int h(int p, int q);
int g(int x)
{
int a = 3, b = 5;
(x ? a : b) = 7;
return h( a, b );
}
gcc generates the error: "error: invalid lvalue in assignment" when compiling as C, but the code compiles without error when compiling as C++.
Edit:
Although ?: can't return an l-value in C, perhaps surprisingly the grammar for ?: is:
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
This means that a ? b : c = d parses as (a ? b : c) = d even though (due to the 'not an l-value' rule) this can't result in a valid expression.
C++ changes the grammar to this:
conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
While the extension to allow conditional-expression to be an l-value in some situations would have made a ? b : c = d valid without the grammar change, the new grammar change means that the expression is now valid but with the different meaning of a ? b : (c = d).
Although I don't have any evidence for it, my supposition that as the grammar change couldn't break compatibility with existing C code, it was more likely that the new grammar would produce fewer surprises with expressions such as:
make_zero ? z = 0 : z = 1;

Conditional operator differences between C and C++

I read somewhere that the ?: operator in C is slightly different in C++, that there's some source code that works differently in both languages. Unfortunately, I can't find the text anywhere. Does anyone know what this difference is?
The conditional operator in C++ can return an lvalue, whereas C does not allow for similar functionality. Hence, the following is legal in C++:
(true ? a : b) = 1;
To replicate this in C, you would have to resort to if/else, or deal with references directly:
*(true ? &a : &b) = 1;
Also in C++, ?: and = operators have equal precedence and group right-to-left, such that:
(true ? a = 1 : b = 2);
is valid C++ code, but will throw an error in C without parentheses around the last expression:
(true ? a = 1 : (b = 2));
The principal practical difference is that in C, evaluation of ?: can never result in a l-value where as in C++ it can.
There are other differences in its definition which have few practical consequences. In C++ the first operand is converted to a bool, in C it is compared against 0. This is analagous to the difference in definition of ==, !=, etc. between C and C++.
There are also more complex rules in C++ for deducing the type of a ?: expression based on the types of the 2nd and 3rd operands. This reflects the possibility of user-defined implicit conversions in C++.
Example code. Valid C++; invalid C.
extern int h(int p, int q);
int g(int x)
{
int a = 3, b = 5;
(x ? a : b) = 7;
return h( a, b );
}
gcc generates the error: "error: invalid lvalue in assignment" when compiling as C, but the code compiles without error when compiling as C++.
Edit:
Although ?: can't return an l-value in C, perhaps surprisingly the grammar for ?: is:
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
This means that a ? b : c = d parses as (a ? b : c) = d even though (due to the 'not an l-value' rule) this can't result in a valid expression.
C++ changes the grammar to this:
conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
While the extension to allow conditional-expression to be an l-value in some situations would have made a ? b : c = d valid without the grammar change, the new grammar change means that the expression is now valid but with the different meaning of a ? b : (c = d).
Although I don't have any evidence for it, my supposition that as the grammar change couldn't break compatibility with existing C code, it was more likely that the new grammar would produce fewer surprises with expressions such as:
make_zero ? z = 0 : z = 1;