while((count++<n) && *s1++=*s2++);
*s1='\0';
i ran this piece of code and got an error lvalue required as left operand of assignment in c
i was able to correct it
while((count++<n) && (*s1++=*s2++));
*s1='\0';
this works fine but i have no idea why. i read other threads in stack overflow saying lvalue should be an assignable value and should not be a constant.i cannot relate it.
is it because (expression) has a value and expression doesnot? i tried to check it with
int c=3;
int b=2;
// printf("%d\n",c==b);
printf("%d\n",(c=b));
both gave the same result of 2.
The reason the first piece of code doesn't compile is && operator has higher precedence in C than =.
So the compiler reads this as ((count++<n) && *s1++) = *s2++, or more generally (A && B) = C.
Related
Hi just wondering if you use a chained assigment in an if condition, would the leftmost variable be used to check the if condition
like a=b=c , its a thats ultimetly checked and not b or c
#include <stdio.h>
int main()
{
int a, b, c =0;
// does this reduce to a == 100 and the variables b or c are not checked if they are == to 100 but simply assigned the value of 100 ?
if( (a = b = c = 100) == 100)
printf( "a is 100 \n");
return 0;
}
The expression is not actually checking a or b or c.
An assignment expression, like any expression, has a value. And in this case it is the value that is stored. However, the actual storing of the value in an object is a side effect so there's no guarantee that it has happened at the time the comparison operator is evaluated.
So the condition is actually more like:
if (100 == 100)
With the assignment to a, b, and c happening in a manner that is unsequenced with respect to the comparison.
This is spelled out in section 6.5.16p3 of the C standard regarding assignment operators:
An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion. The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.
The condition is always true. Your code is equivalent to:
a = 100;
b = 100;
c = 100;
printf( "a is 100 \n");
I have three variables: a, b, c. Let's say they are integers. I want to find the first non-zero value among them, in that particular order, without looping. The following seems to work, but I am not sure if that is because I am lucky, or because the language guarantees it:
int main(int argc, char *argv[]) {
int a = 0;
int b = 3;
int c = 5;
int test;
if ((test = a) != 0 || (test = b) != 0 || (test = c) != 0) {
printf("First non-zero: %d\n", test);
} else {
printf("All zero!\n");
}
return 0;
}
Is the repeated assignment with short-circuiting shown here guaranteed to work as intended, or am I missing something?
This might be one place where a three-letter answer would be acceptable, but a two-letter answer might require more explanation.
It would!
Because of the nature of the OR operator if any of the condition is
true then the test stops.
Thus i think what you did was basically equivalent to:
test = a != 0 ? a : b != 0 ? b : c != 0 ? c : 0;
printf("%d\n",test);
but heck yours looks good.
[update]
As per what chqrlie mentioned it can be further simplified to:
test = a ? a : b ? b : c;
Yes, your expression is fully defined because there is a sequence point at each || operator and the short circuit evaluation guarantees that the first non zero value assigned to test completes the expression.
Here is a crazy alternative without sequence points that may produce branchless code:
int test = a + !!a * (b + !!b * c);
printf("%d\n", test);
The code is very bad practice but it is guaranteed to work fine.
This is because the || and && operators have special characteristics - unlike most operators in C, they guarantee that the evaluation of the left operand is sequenced (executed) before the evaluation of the right operand. This is the reason that the code works. There's also a guarantee that the right operand will not be evaluated if it is sufficient to evaluate the left one ("short circuit"). Summarized in C17 6.5.14/4:
Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; if the
second operand is evaluated, there is a sequence point between the evaluations of the first
and second operands. If the first operand compares unequal to 0, the second operand is
not evaluated.
"Sequence point" being the key here, which is what gives the expression a deterministic outcome.
Had you used pretty much any other operator (like for example bitwise |), then the result would be undefined, because you have multiple side effects (assignments) on the same variable test in the same expression.
A more sound version of the same algorithm would involve storing the data in an array and loop through it.
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
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.
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.