syntax of comparison between two different things - c

Following program gives error
#include<stdio.h>
int main ()
{
int a=10,b;
a>=5?b=100:b=200;
printf("\n%d",b);
}
the error is
ka1.c: In function ‘main’:
ka1.c:5: error: lvalue required as left operand of assignment
now if I replace the line
a>=5?b=100:b=200;
by
a>=5?b=100:(b=200);
and then compile then there is no error.
So I wanted to know what is wrong with
a>=5?b=100:b=200;

The ternary operator (?:) has higher precedence than the assignment operator (=). So your original statement is interpreted as:
((a >= 5) ? (b = 100) : b) = 200;
Write it like this instead:
b = (a >= 5) ? 100 : 200;
This is idiomatic C. (The brackets around the condition are not really necessary, but they aid readability.)

You're using the ternary operator incorrectly. Both of your examples are wrong, even though one compiles. The expression evaluates to either the second or third sub-expression depending upon the truth value of the first.
So a ? b : c will be the same thing as b if a is true, or c if a is false.
The proper way of using this operator is to assign the result to a variable:
b = a>= 5 ? 100 : 200;

Because it tries to do: (a>=5?b=100:b)=200
But the thing in parentheses is not lvalue.

Related

Question regarding operator precedence in C

I'm starting to learn to program in c, and I thought I was already pretty confident with the precedence of operators, until I did this:
a > b ? c = a : (c = b);
Of course at the first time I didn't use parenthesis on the last sentence, but since that ended up causing compiling issues I searched how to solve that problem on this forum and I read that adding parenthesis could do the job. However, I thought that the expressions inside parenthesis get executed before anything else written in the same line, which would mean that the c = b sentence was executed first and then the ternary operator. I did something similar but easier to read in order to get a better idea of what was happening with this operator precedence thing and tried executing this line:
printf("Number is %d", i) + (i = 5);
I know this expression returns returns a value, but since I don't need it and this isn't a line that I will keep for more than 5 seconds, I won't store it in any variable. What gets my attention in this case is that, when I execute the code, I doesn't show up on the screen with the value 5, but instead it uses the previous value, which means that the computer is just reading it from left to right. When I do:
(i = 5) + printf(Numer is %d, i);
it first does the assignment of i and only after that the printf function is executed. My question is: how does the computer execute an expression that uses operators of different orders of precedence? It clearly doesn't run first the operator with the highest precedence, because in the first printf the value stored wasn't the one assigned on the parenthesis, but it also doesn't just read from left to right because in that case there would be no operator precedence. How does it work?
Parenthesis and operator precedence only dictate how operands are grouped. It does not dictate the order of evaluation.
In this expression:
a > b ? c = a : (c = b);
The three parts of the ternary operator are a > b, c = a, and c = b respectively. This operator also has the property that only one of the second and third clause are evaluated, based on the result of the first. Formally speaking, there is a sequence point between the evaluation of the first clause and of either the second or third. So a > b is first evaluated. If it is nonzero, c = a is evaluated, otherwise c = b is evaluated.
In this expression:
printf("Number is %d", i) + (i = 5);
There is nothing that dictates whether printf("Number is %d", i) or i = 5 is evaluated first. Unlike the ternary operator, there is no sequence point between the evaluation of the operands of the + operator. This expression also has a problem: i is both read and written in the same expression without a sequence point. Doing so triggers undefined behavior. This is also true for:
(i = 5) + printf(Numer is %d, i);
On a side note, this:
a > b ? c = a : (c = b);
Can be more clearly written as:
c = a > b ? a : b;

"error: lvalue required as left operand of assignment" in conditional operator

I'm new to C and today I learnt "?" operator which is the short type of if-else statement. However, when I execute this code:
int b;
int x;
b=3<2?x=12:x=34;
I get an error "error: lvalue required as left operand of assignment". I don't understand why it happens. Process in my mind is that the program first assigns 34 to x, then it assigns value of x,which is 34, to b.
On the other hand, I can use the statement as
int b;
int x;
b=3<2?x=12:(x=34);
without any errors. I looked to my book but nothing helped. Why can't I use the first statement? What is my computer trying to do?
Thanks...
+1 for interesting question - it highlights two differences between C++ and C.
(1) The evaluation rules for ternary expressions are different in C and C++
C++ parses as follows
logical-OR-expression ? expression : assignment-expression
It is therefore parsing your statement by matching assignment-expression to x=34
b = 3<2 ? x = 12 : (x = 34);
But C parses like this
logical-OR-expression ? expression : conditional-expression
x = 34 is not a conditional-expression so your statement gets parsed like
b = (3<2 ? x = 12 : x) = 34;
(2) The conditional operator in C++ can return an lvalue, whereas C cannot. Hence, the following is legal in C++ but not in C:
b = (3<2 ? x = 12 : x) = 34;
Verified on ideone.com for C and C++ compilers.
See also these links
Errors using ternary operator in c for diff between C and C++ ternary operator
Conditional operator differences between C and C++ for diff in lvalue rules

lvalue required as left operand of assignment -error in ?: in C

why does a<=20? b=10 : c=30; give lvalue error?
error: lvalue required as left operand of assignment
is it because b=10 and c=30 are statements and not expressions?
It is because conditional operator has higher precedence than assignment operator and the expression is interpreted as
((a<=20)? (b=10) : c)=30;
What is returned from conditional operator is not a lvalue (N15706.5.15, footnote 110), so the program will emit compile error.
You can use parentheses to overcome this problem of precedence.
a<=20? (b=10) : (c=30);
Using normal if statement should be better unless you have some reasons like:
Doing code golf
Trying to make your program hard to read
Want to use what is returned from the expression
if (a <= 20) {
b = 10;
} else {
c = 30;
}
Your code is missing parentheses around assignments.
This compiles and runs correctly:
int a = 20, b = -1, c = -1;
a<=20? (b=10) : (c=30);
printf("b=%d, c=%d\n", b, c);
Demo.
Note: It goes without saying that such (mis)use of ternary operator has negative impact on readability of your code, and should be avoided in favor of a regular if statement.

Use of the ternary operator: var ? 12-var : 0

Hey thank you very much for your time! I'm having trouble understanding the syntax of a statement in my audio coding textbook. In one example there is a print function that goes like this
printf("%d semitones up or %d semitones down\n", interval,
interval ? 12-interval : 0 );
The part I don't understand is the conditional operator, or "?". It seems like I should just read it as "if interval does not equal 0, interval = 12 - interval" but the syntax here seems strange. I'm used to the conditional operator being a more fleshed out statement, like:
a = b > c ? b : c;
"If b is bigger than c, than a = b; else a = c"
Could someone point me to any other reference for this, or explain more about this syntax? I can't find similar examples.
You're almost right, but there's no assignment taking place. It's saying "if interval is non-zero, pass 12 - interval to the printf statement, otherwise pass 0".
In general the ternary operator looks like this:
a ? b : c
Where a, b, and c are all expressions. If a evaluates to non-zero, the ternary operator evaluates as if it were b, and if a evaluates to zero, the ternary operator's result is the result of evaluating c.
Your second example is a combination of the ternary operator and the assignment operator. The ternary operator itself doesn't perform any assignments.
Any expression that results in a boolean will do. In the case of C, where integers can be used as booleans, the value 0 is considered false and anything else is considered true.
So, in your case, interval ? 12-interval : 0, means: if interval is nonzero, use 12-interval, otherwise, use 0. To be extra verbose, you could rewrite it to:
interval != 0 ? 12-interval : 0

Unexpected error with conditional operator

The code below compiles well
int a=5,b=4,c;
a>b?30:40;
Also does,
int a=5,b=4,c;
a>b?c=30:40;
But why this does not work?
int a=5,b=4,c;
a>b?c=30:c=40;
You are being bitten by precedence. ?: has very low precedence, but not as low as = or , (see the operator precedence table).
Your code is parsed as:
(a>b ? c=30 : c) = 40;
Rather than:
a>b ? c=30 : (c=40);
You don't need parenthesis around c=30 because ? and : act like parentheses to the expression within.
Believe it or not, (a>b ? c=30 : c) = 40 is valid C++ (but not valid C). The expression (a>b ? c=30 : c) is an lvalue referencing the variable c, to which 40 is assigned.
You've run into a precedence problem with the = operator. If you insist on assignment inside of your ternary operator, merely wrap the sub expressions in parentheticals:
int d = a > b ? (c = 30) : (c = 40); // explicit precedence
The last one:
int a=5,b=4,c;
a>b?c=30:c=40;
fails because it's trying to assign 40 to a>b?c=30:c, which obviously won't work. The = has lower precedence, and a>b?c=30:c is a valid expression (though you can't assign to it). The = in the c=30 part is sort of an exception because it's in the middle of the ternary operator, between the ? and the :. To fix it you'd simply need to add parentheses around the c=40 so that it's evaluated as a single value for the 'else' part of the ternary operator, i.e. a>b?c=30:(c=40);
The second example
a>b?c=30:40;
doesn't assign anything to c unless a is greater than b... which it is when a is 5 and b is 4, as in this case; but note that if a were not greater than b, no assignment would occur.
From the first example
a>b?30:40
is a valid expression, with a value of 30 or 40, but you're not doing anything with that value so of course it serves no purpose there.
Of course, you'd normally use something more like:
c = a>b ? 30 : 40;
where a>b ? 30 : 40 will evaluate to 30 or 40, which is then assigned to c. But I suspect you know that and simply want to know why the c=40 is not treated as a single value for the 'else' part of the ternary operator in the last example.

Resources