mux said:
Hi
I found out that the following piece of code throws an error.
1 #include "stdio.h"
2
3 int main()
4 {
5 int a,b;
6 a= 10;
7 a>10?b=20:b=30;
8 printf("%d",b);
9 }
and the error was:
$ gcc -g -o test test.c
test.c: In function `main':
test.c:7: error: invalid lvalue in assignment
However, when you rewrite line 7 as:
a>10?b=20
b=30);
Then there is no error. Why it is so? I thought conditional operators where
an macro-like replacement of a simple if-else statement.
Informally speaking, the conditional operator `?:' has
"higher precedence than" or "binds more tightly than" the
assignment operator `='. (More formally, the Standard that
defines the C language specifies a grammar for the language,
and the grouping of operators with operands is a consequence
of the way the grammar is defined. Usually it's easier to
use terms like "precedence" when talking to humans rather
than to parsers.)
Of course, saying that one operator has higher precedence
than another "because it's defined that way" merely avoids
the issue: *Why* is the language defined this way? The answer
is that the inventors chose rules that would lead to "natural-
looking" expressions in the most common cases. The multiplication
operator `*' has higher precedence than the subtraction operator
`-' because people expect `a*b-c' to mean `(a*b)-c' rather than
`a*(b-c)'. The assignment operator `=' has a very low precedence
because people expect `x=a+b' to mean `x=(a+b)' and not `(x=a)+b'.
So: The assignment operator has very low precedence; it
"binds less tightly" than almost all other operators. Your
original statement is therefore understood as
((a>10)?(b=20):b)=30;
.... and now, I suppose, you can understand gcc's complaint:
the thing on the left-hand side of the assignment operator
is not something one can assign to. It's analogous to writing
`x+1=b'.
When you repair the expression by inserting explicit
parentheses, the result is parsed as
(a>10)?(b=20)
b=30);
.... which makes sense. You may be wondering why the middle
set of parentheses wasn't actually required: I've just been
telling you that the assignment in `b=20' has lower precedence
than the conditional operator, which might lead you to think
that your final version would be parsed as
((a>10)?b)=20
b=30);
.... which is complete nonsense. Well, that's where notions
like "precedence" are too simplistic for a good explanation.
The Standard's grammar is constructed in such a way that this
nonsensical parse is not attempted; the "inner" assignment is
"known" to occur in a context where it must "bind more tightly"
than the `?:'. No such simple escape is possible for the
third sub-expression, though: we're back into "open context."
By the way, the usual form for your statement is something
more like
b = a>10 ? 20 : 30;
.... which once again exhibits the desirability of "low precedence"
for the assignment operator.
Is there any other such odd things (not behavior) in using a conditional
operator I need to be aware of?
I don't know how to answer this, because something that
seems odd to you may seem perfectly normal to me or to anyone
with greater experience of the language. "Oddity is in they
eye of the beholder."
For that matter, is there any website that would point to such quirks in c?
Every web site and every text or reference work on any
subject at all probably contains something that someone would
consider a "quirk." If you can give a rigorous definition of
"quirk" there might be a way to answer the question -- but if
you could give such a definition, you'd probably no longer need
to have the question answered!