This question already has answers here:
Errors using ternary operator in c
(5 answers)
Closed 8 years ago.
(k < m ? k++ : m = k)
This particular expression gives compile time error saying lvalue required. The problem is with k++. Not able to understand what is wrong in this expression.
The input
k < m ? k++ : m = k;
is parsed as
((k < m) ? k++ : m) = k;
where k++ is an rvalue and m is an lvalue. So the conditional is an rvalue.
You probably mean something like
(k < m) ? k++ : (m = k);
Better use
if (k < m) {
k++;
} else {
m = k;
}
instead.
You can see the C precedence table e.g. here: http://en.cppreference.com/w/c/language/operator_precedence.
The terms "lvalue" and "rvalue" mostly mean "things that you can write left of an assignment" and "things you can only write on the right side of an assignment", resp. C.f. "Are literal strings and function return values lvalues or rvalues?".
An easier example to see the semantics of ?:: For a uint8_t k, what does condition ? k : k + 1 mean?
Easy to see the former part k is an lvalue with the type uint8_t.
The latter expression k + 1 is somewhat trickier, though. Being the result of an arithmetic expression, it is an rvalue. Also it's not a uint_8 but int.
The common type of uint8_t and int is int. So in total condition ? k : k + 1 is an rvalue expression with the type int.
Related
#include <stdio.h>
int main(void){
int n = 0, y = 1;
y == 1 ? n = 0 : n = 1;
if (n)
printf("YES");
else
printf("NO");
return 0;
}
Can some one explain why does the line with the ternary operator give a lvalue error. I have a very abstract idea of what lvalue is. Let me give my abstraction, correct me if I am wrong. lvalue is typically the address or we can say the variable where we store a constant value and the value of a variable or a constant is a rvalue. But I don't understand why is there an lvalue error in the assignment part of the ternary operator which states n = 0 : n = 1. It would be really helpful if I could get a proper understanding of what is wrong with my code.
The ternary operator ?: has higher precedence the assignment operator =. So your expression parses as:
(y == 1 ? n = 0 : n) = 1;
This gives you an expression on the left side of the assignment that is not an lvalue and therefore not assignable.
The ternary operator evaluates to either the value of the second part or the value of the third part, and these values are what you want to assign to n, so you could instead write it as:
n = y == 1 ? 0 : 1;
Or you could invert the condition and get rid of the ternary entirely:
n = y != 1;
The reason is that the ternary operator has higher precedence than assignment. So the expression is parsed as if you'd written:
(y == 1 ? n = 0 : n) = 1;
This is not a valid assignment because the result of the conditional operator is an rvalue, not an lvalue, so you can't assign to it.
You can solve the problem by adding parentheses around the assignments.
y == 1 ? (n = 0) : (n = 1);
But since you're assigning to the same variable, the more normal way to write this would be:
n = y == 1 ? 0: 1;
You can also take advantage of the fact that the result of a comparison operator is a boolean, either 0 or 1, so you can write simply:
n = y != 1;
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
In chapter 4, section Compound Assignment of the book: C Programming: A Modern Approach, 2nd Edition, says:
Note that I've been careful not to say that v += e is “equivalent” to v = v + e. One problem is operator precedence: i * = j + k isn't the same as i = i * j + k.
I write a program to compare i * = j + k with i = i * j + k.
but the result is the same.
#include <stdio.h>
int main() {
int i = 1;
int j = 2;
i *= j + 10;
int k = 1;
k = k * j + 10;
printf("j=%d k=%d\n", i, k);
}
result is:
j=12 k=12
So my question is: why isn't i * = j + k the same as i = i * j + k ?
Thanks for all the replies. I have misunderstood the compound assignment operator. And I have wrote a misleading test.
I'd like to say you guys are great to discuss technical questions and learn together. I can not find such a great website and people like you in China.
If you get confused, have a look at the operator precedence chart
In your case,
i *= j + 10;
is same as
i *= (j + 10);
which is same as
i = i * (j + 10);
However,
k = k * j + 10;
is same as
k = (k * j) + 10;
As per the output: Try different values.
For example, if I chose i and k as 2, the output will be
i=24 k=14
Short answer:
It is quite obvious that they refer to operator precedence. That is:
The expression i = i * j + k is equivalent to i = (i * j) + k.
But i *= j + k is equivalent to i = i * (j + k);.
Now of course if you use bad input such as i=1, j=1, k=1 the result of both of these expressions will be the same, by bad luck. Not because of the C language but because of elementary school math.
(if you are a beginner you can stop reading here)
Advanced answer regarding equivalence of assignment operators:
Compound assignment (the *=) is not exactly equivalent to simple assignment =. The standard C17 6.5.16.2 says:
A compound assignment of the form E1 op = E2 is equivalent to the simple assignment expression E1 = E1 op (E2), except that the lvalue E1 is evaluated only once
Meaning that if reading the operand E1 includes a side effect, compound assignment is different from simple assignment. Consider this artificial but valid example:
int foo (void)
{
static int n=0;
return ++n;
}
int array[3] = {1,2,3};
int* ptr = array;
#define FOO *(ptr + foo())
FOO += 1; gives an array 1 3 3 but FOO = FOO + 1; could give an array 1 4 3 1). This is because of the extra side-effect in the latter case.
1) The order of evaluation between the left FOO and right FOO is unspecified, so it can give different results - it is unspecified behavior.
#include <stdio.h>
#define max(x,y)(x)>(y)?x:y
int main() {
int i = 10;
int j = 5;
int k = 0;
k == max(i++, ++j);
printf("%d%d%d ", i, j, k);
return 0;
}
I know the answer. It is 11 7 0 but how? please help me with the execution of the ternary operator.
The statement
k==max(i++,++j);
is expanded to
k==(i++)>(j++)?i++:j++;
Note that == has higher precedence than ?: operator and therefore the above expression is equivalent to
( k == ((i++)>(j++)) )?i++:j++;
Since (i++)>(j++) will be true, therefore k == ((i++)>(j++)) is evaluated as false and hence j++ (and it's value become 7) will be evaluated (i++ will be skipped).
NOTE: The above expression does not invoke undefined behavior because there exists sequence point between the evaluation of the first operand of the ternary operator and the second or third operand. For example, the expression
a = (*p++) ? (*p++) : 0
has well defined behavior.
This question is definitely a trick question that will catch many unsuspecting C programmers. The different responders here have more than 100 years of compounded experience in C, yet it took several tries to get this right:
The expression k == max(i++, ++j); expands to:
k == (i++)>(++j)?i++:++j;
Which is parsed as this (== has lower precedence than >, but higher precedence than ?):
(k == ((i++) > (++j)))
? i++
: ++j;
The ternary operator evaluates the test (i++)>(++j), which is true for the values in the program, hence evaluates to 1, different from the value of k, so it proceeds to evaluate the third expression j++, which increments j a second time and returns the intermediary value 6. There is a sequence point between the test and the branch that is executed, so it is OK to increment j twice. The second branch is not executed at all since the test evaluated to false.
i is incremented once, its value becomes 11.
j is incremented twice, its value is 7.
k is not modified by the above statement, because == is the comparison operator, not the assignment operator.
Hence the output is 11 7 0
Notes:
The program uses a macro max that evaluates its arguments more than once and they are not properly parenthesized in the expansion: 2 errors that illustrate the shortcomings of macros. This macro should be names MAX to emphasize the fact that its arguments should not have side effects and its expansion should be fully parenthesized this way:
#define MAX(x,y) ((x) > (y) ? (x) : (y))
A better alternative is to make it an inline function:
static inline int max(int x, int y) {
return x > y ? x : y;
}
If the program had this statement:
k = max(i++, ++j);
The output would be 12 6 11 because unlike ==, = has lower precedence than ? so the statement would expand to:
k = ((i++) > (++j))
? i++
: ++j;
You can study the table of operator precedence for C. There are in my humble opinion too many levels and it is very difficult to memorize all of them, especially since some of them are rather counter-intuitive: print a copy and keep it handy or make a bookmark. When in doubt, use parentheses.
You're using a double equal sign, which is a comparison. k==max(i++,++j); compares the return value of max to k, which is 0.
Instead, try changing the == to =.
int main(void)
{
int i = 10, j =20;
j = i, j ? (i, j) ? i : j : j;
printf("%d %d", i, j);
return 0;
}
What is the output?
Please somebody guide me how to interpret the nested ternary operator in this case.
C is defined by a language grammar; a precedence table is a handy condensing of the grammar into something that humans can take in at a glance, but it doesn't exactly correspond to what the grammar specifies.
You may need to consult the language grammar in order to resolve associativity around a ternary operator. Personally I always explicitly use parentheses so that a reader who's not a language lawyer can still understand what's going on (and so that I don't make mistakes).
An example is:
c ? c = a : c = b
which must be parsed as
(c ? c = a : c) = b
which is illegal in C, since the ternary operator does not give an lvalue. Incidentally, the C++ grammar is different; in that language this is parsed as
c ? c = a : (c = b)
which is legal; and also the ternary operator can give an lvalue in C++.
In your case, the question is which of the following it is:
Z = ((i , j) ? X : Y)
Z = (i , (j ? X : Y))
(Z = i, j) ? X : Y
(Z = i), (j ? X : Y)
I believe the latter is correct here, so you should end up with j = i plus an expression with no side-effect.
What you have here is hopefully code you have read and you want to get rid of, not code you actually use.
You have a combination of two unparenthesed ternay operators and two uses of the comma operator.
Despite no use of parentheses, the nesting of ?: is unambiguous:
a ? b ? c : d : e
can only mean
a ? ( b ? c : d) : e
as there is no other way to interpret it.
The 2nd comma operator is in parentheses, so it is unambiguous as well.
The only point of doubt is the comma operator at the start, where you might want to consult a precedence table.
Here we see that , has the lowest precedence and thus we have
(j = i), (j ? (i, j) ? i : j : j);
which is a comma operator with an assignment as first expression and an unevaluated other expression as second expression, which is the result.
In short, if we omit the right side, which isn't used nevertheless, we just have j = i, but this expression lacks unreadability.
So the output is 10 10.
Great trap, this expression... but as it is written, the answer doesn't cover this. If I erroneously evaluated it as j = j ? i : j; I would get 10 10 as well.
This question already has answers here:
Is a += b more efficient than a = a + b in C?
(7 answers)
Closed 9 years ago.
what is the difference between i = i + j; and i += j; in C?
Are they equivalent? Is there any side effect of i?
I was trying to check the assignment mechanism in C using the GCC compiler.
They're almost the same. The only difference is that i is only evaluated once in the += case versus twice in the other case.
There is almost no difference, but if i is a complex expression, it is only computed once. Suppose you had:
int ia[] = {1, 2, 3, 4, 5};
int *pi = &(ia[0]); // Yes, I know. I could just have written pi = ia;
*pi++ += 10;
// ia now is {11, 2, 3, 4, 5}.
// pi now points to ia[1].
// Note this would be undefined behavior:
*pi++ = *pi++ + 10;
i = i + j is equivalent to i += j but not same.
In some cases(rare) i += j differs from i = i + j because i itself has a side effect.
Also one more problem is operator precedence i.e
i = i * j + k;
is not same as
i *= j + k;
The two statements i = i + j and i += j, are functionally same, in first case you are using the general assignment operation, while the second one uses the combinatorial assignment operator. += is additive assignment operator (addition followed by assignment).
The use of combinatorial assignment operators generates smaller source code that is less susceptible to maintenance errors and also possibly a smaller object code where it would also run faster. Compilation is also likely to be a little faster.
Syntactic sugar baby.
Any differences are just going to come down to compiler implementation.
http://en.wikipedia.org/wiki/Syntactic_sugar
In both cases i (the variable or expression being assigned) must be an lvalue. In most simple cases this will yield code that is identical in both cases so long as i is not declared volatile.
However there are a few cases where a lvalue can be an expression involving operators, and this may cause evaluation of i twice. The most plausible example of an lvalue expression that might be used in that way is perhaps simple dereferencing of a pointer (*p):
*p = *p + j ;
*p += j ;
may generate different code, but it is trivially optimised so I would expect not even without optimisation enabled. Again p cannot be volatile, otherwise the expressions are semantically different.
A less plausible scenario is to use a conditional operator expression as an lvalue. For example the following adds j to b or c depending on a:
(a ? b : c) += j ;
(a ? b : c) = (a ? b : c) + j ;
These might generate different code - the compiler might reasonably not spot that idiom and apply an optimisation. If the expression a has side effects - for example were the expression getchar() == '\n' or a is volatile (regardless of b or c), then they are not equivalent since the second would evaluate to:
c = b + j for the input "Y\n",
b = b + j for input "\n\n",
c = c + j for input "YN".
These points are of course mostly irrelevant - if you write code like that and it does things you did not expect, sympathy may be in short supply!