Quirk in Conditional Operator?:

M

mux

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.

Is there any other such odd things (not behavior) in using a conditional
operator I need to be aware of?

For that matter, is there any website that would point to such quirks in c?

Any help would be greatly appreciated.

Regards,
Muralidhar
(e-mail address removed)
 
M

Mark A. Odell

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);

What happens when you write it for clarity? E.g.

b = a > 10 ? 20 : 30;

Try that. If you are a parenaphile try:

b = (a > 10) ? 20 : 30;
 
J

Joona I Palaste

mux said:
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:

Then there is no error. Why it is so? I thought conditional operators where
an macro-like replacement of a simple if-else statement.

They're nothing of the sort. The conditional operator is a real, kosher,
all-singing, all-dancing C operator with C semantics. Thus, it must obey
C rules about operator precedence and lvalues.
In an assignment operation, the RHS must be a modifiable lvalue, and I
don't think the conditional operator produces such things. If I know my
precedence rules, what you are doing is equivalent to:
(a>10 ? (b=20) : b) = 30;
which won't work. However I think you meant:
(a>10) ? (b=20) : (b=30);

Note that you can't do this:
(a<10 ? a : b) = 30;
but you can do this:
*(a<10 ? &a : &b) = 30;
because the unary * (indirect through) operator turns rvalues of type
"pointer-to-T" into modifiable lvalues of type "T".

--
/-- Joona Palaste ([email protected]) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"The day Microsoft makes something that doesn't suck is probably the day they
start making vacuum cleaners."
- Ernst Jan Plugge
 
E

Eric Sosman

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!
 
M

Murali

Wow...That was one of the most elegant answer I have seen in years.

Thanks for helping me out. and true that Quirk is in the eyes of the
beholder. But I felt that someone might be gracious enough to put a warning
sign for such tiny titbits that would life of a programmer(and a debugger)
much easier.

Thanks once again

Regards
Muralidhar
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top