?: as an lvalue

R

Richard

Bartc said:
bert said:
Rahul wrote:
int main()
{
int aa=0,b=0;
1>0?aa:b = 10;
printf("value %d %d\n",aa,b);
return(0);
}

and output is value 0 0
The result of the ?: operator is not an lvalue, and cannot be
assigned to.

If you want to conditionally assign to one of two objects, it's
probably clearer to write it in full:

if (1>0)
aa = 0;
else
b = 10;

If you really want unreadable code, I suppose you could do this:
int *ip[2] = {&b,&aa};

*ip[1>0] = 10;

but if I worked with you I wouldn't thank you for it :)

For such requirements, I have written - and
been satisfied with - code of the style:

*(i > 0 ? &aa : &b) = <complicated expression>;

Well done - you'll make maintainers very happy in years to come.

I can't decide whether that's sarcasm from you, or real praise.

I don't think it was praise..
The main thing "wrong" with your alternative
is the omission of a block structure.

{
int v = complicated expression;
if (i)
aa = v;
else
b = v;
}

would make it perfectly clear to a maintainer
in years to come that the only purpose of v
was to be assigned either to aa or to b.

There was nothing much wrong with the original syntax:

a ? b : c = x;

(maybe better as (a ? b : c) = x;)

except that C doesn't allow it, and it's unfortunate that the legal format
is a little messy:

So nothing wrong with it except for the fact that C doesnt allow it? Are
you trolling or just up for some sort of special award?
*(a ? &b ? &c) = x;

This is what the programmer wants to do, so why force him to create
unnecessary statements and to duplicate expressions, or declare unnecessary
temporary variables? All extra clutter.

Dont be ridiculous. Everything is a trade off between readability,
maintainability and efficiency. The above is , IMO, too clever for its
own good. And its certainly no more efficient.
Exactly why a?b:c can't appear like that on the left-hand-side of an
assignment is a bit of a mystery;

There is no mystery about it.
after all a, a.b, a->b, a and so on can
all appear on the lhs without the programmer having to insert explicit
address-of operators.


And that has to do with ?: how?
 
B

Bartc

Richard said:
So nothing wrong with it except for the fact that C doesnt allow it? Are
you trolling or just up for some sort of special award?


Dont be ridiculous. Everything is a trade off between readability,
maintainability and efficiency. The above is , IMO, too clever for its
own good. And its certainly no more efficient.

You can argue the same way about using a?b:c as an rvalue.
Exactly why a?b:c can't appear like that on the left-hand-side of an
assignment is a bit of a mystery;

There is no mystery about it.
after all a, a.b, a->b, a and so on can
all appear on the lhs without the programmer having to insert explicit
address-of operators.


And that has to do with ?: how?


a: You can write a = x without writing *(&a) = x
a.b: You can write a.b = x without writing *(&a + offsetof b) = x
(I think offsetof is more complex than that)
a->b: You can write a->b = x without writing *(&a + offsetof b) = x
a: You can write a = x without writing *(a+b) = x
a?b:c: You CAN'T write a?b:c = x without writing *(a ? &b : &c) = x

So the mystery is why the compiler gives special dispensation to those other
forms when an lvalue is expected, but not the ?: form.

Someone will say, for the same reason as a+b can't usually be an lvalue, but
I think ?: is a little different.
 
B

Ben Bacarisse

Richard said:
"Bartc" <[email protected]> writes:

There is no mystery about it.

Why not help by explaining it then? It is a mystery to me as well, so
least least two people would benefit from your explanation.

In particular, a Closely Related Language, *does* allow the result of
a conditional operator to be an lvalue. I can't think, off-hand, of a
reason for this difference.
 
A

Andrey Tarasevich

Richard said:
Well done - you'll make maintainers very happy in years to come.

What on earth is wrong with

v= complex expr;
if(i)
aa=v;
else
b=v;

Same number of characters give or take too .... Easy to see
flow/assignment in a debugger too. Very easy to read.

There's nothing wrong with it except that it is a _statement_, while the
previous form is an _expression_. While I personally strongly prefer the
former in "normal" code, there are still quite a few expression-based
idiomatic tricks in C programming, which require the use of the
expression form.

I don't see the point in starting an argument about this. If at all, you
should probably direct your question to the authors of the language,
asking them why they introduced this "redundant" ?: operator in the
first place.
 
D

Dave Hansen

Rahul said:




This is a syntax error (which therefore requires the implementation to
diagnose it as such). The syntax of the conditional operator is:

I believe the syntax is legal. It just doesn't do what the OP wanted
it to.

Consider that it parses as

(1>0)?(aa):(b=10);

Change it to 1<0?aa:b=10; and see the result...

Regards,

-=Dave
 
E

Eric Sosman

Dave said:
I believe the syntax is legal. It just doesn't do what the OP wanted
it to.

Consider that it parses as

(1>0)?(aa):(b=10);

Would you care to place a small wager on that?

You could refer to the formal grammar in the Standard
to settle the question, or you could ask informally which
of = and ?: "binds more tightly." The parse you suggest
would follow if = binds more tightly, in which case

x = a ? b : c;

would parse as

(x = a) ? b : c;

Since we know that it actually parses as

x = (a ? b : c);

you may be about to lose some money ...
 
R

Richard

Ben Bacarisse said:
Why not help by explaining it then? It is a mystery to me as well, so
least least two people would benefit from your explanation.

Huh? I must be missing something here or I will be first to apologise.

We already know that

*(c?x:y)=v;

is ok where x and y are pointers.

But (c?x:y)=v;

I dont really know what to say.
 
A

Andrey Tarasevich

Richard said:
> ...
But (c?x:y)=v;
I dont really know what to say.

Is there any reason why you believe that the property of "being an
lvalue" should be necessarily lost in the process of selection from two
lvalues of the same type?

I mean I'm OK personally with the way it works in C. I just like to know
what is it exactly in '(c?x:y)=v' that triggers a "I don't really know
what to say" reaction from some people.
 
R

Richard

Andrey Tarasevich said:
Is there any reason why you believe that the property of "being an
lvalue" should be necessarily lost in the process of selection from
two lvalues of the same type?

I mean I'm OK personally with the way it works in C. I just like to
know what is it exactly in '(c?x:y)=v' that triggers a "I don't really
know what to say" reaction from some people.

because its not a macro? it returns a value. I dont know the legalise
words but it seems "obvious" enough to me, but again it might be because
I am tainted.
 
W

Willem

Eric wrote:
) Dave Hansen wrote:
)> Consider that it parses as
)>
)> (1>0)?(aa):(b=10);
)
) Would you care to place a small wager on that?
)
) You could refer to the formal grammar in the Standard
) to settle the question, or you could ask informally which
) of = and ?: "binds more tightly." The parse you suggest
) would follow if = binds more tightly, in which case

Technically, it would also follow if = binds equally tightly.
Left-to-right and all that.

) x = a ? b : c;
)
) would parse as
)
) (x = a) ? b : c;

Again, purely technically, it would not if = were to bind equally tightly.

) Since we know that it actually parses as
)
) x = (a ? b : c);
)
) you may be about to lose some money ...

I'm not going to bet on it though.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
A

Andrey Tarasevich

Dave said:
I believe the syntax is legal.

Legal where? In C? No, it is not.
It just doesn't do what the OP wanted
it to.

It doesn't do anything. It is illegal in C.
Consider that it parses as

(1>0)?(aa):(b=10);

But it doesn't parse like that in C.
Change it to 1<0?aa:b=10; and see the result...

The result will be the same: a diagnostic message triggered by the
attempt to assign to a non-lvalue.
 
W

Willem

Andrey wrote:
) Richard wrote:
) > ...
)> But (c?x:y)=v;
)> I dont really know what to say.
)
) Is there any reason why you believe that the property of "being an
) lvalue" should be necessarily lost in the process of selection from two
) lvalues of the same type?
)
) I mean I'm OK personally with the way it works in C. I just like to know
) what is it exactly in '(c?x:y)=v' that triggers a "I don't really know
) what to say" reaction from some people.

Well then why not also make it possible for functions (that return
pointers) to be lvalues ?

returnspointertostruct(foo)->bar = baz;

Or is that already legal ?


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
F

Flash Gordon

Bartc wrote, On 31/03/08 18:45:
Richard said:
So nothing wrong with it except for the fact that C doesnt allow it? Are
you trolling or just up for some sort of special award?

Dont be ridiculous. Everything is a trade off between readability,
maintainability and efficiency. The above is , IMO, too clever for its
own good. And its certainly no more efficient.

You can argue the same way about using a?b:c as an rvalue.
Exactly why a?b:c can't appear like that on the left-hand-side of an
assignment is a bit of a mystery;
There is no mystery about it.
after all a, a.b, a->b, a and so on can
all appear on the lhs without the programmer having to insert explicit
address-of operators.

And that has to do with ?: how?


a: You can write a = x without writing *(&a) = x


You can't do 3 = x
a.b: You can write a.b = x without writing *(&a + offsetof b) = x

You can't do 5.b or a.5
(I think offsetof is more complex than that)
a->b: You can write a->b = x without writing *(&a + offsetof b) = x

You can't do 5->b or b->5
a: You can write a = x without writing *(a+b) = x


Unless b is a pointer or array name you can't do 5
a?b:c: You CAN'T write a?b:c = x without writing *(a ? &b : &c) = x

You can do a?1:2
So the mystery is why the compiler gives special dispensation to those other
forms when an lvalue is expected, but not the ?: form.

Someone will say, for the same reason as a+b can't usually be an lvalue, but
I think ?: is a little different.

I think you are wrong. Look at the fact that all of the other operators
you mention *require* at least one of the operands to be an object but
neither + nor ?: require and operand to be an object. Then you should
see why it is natural for a?b:c = x to be wrong.
 
A

Andrey Tarasevich

Richard said:
because its not a macro? it returns a value. I dont know the legalise
words but it seems "obvious" enough to me, but again it might be because
I am tainted.

Well, unary '*' operator is also not a macro. Yet it evaluates to an
lvalue. Same for '[]' operator (by definition). Do you find this strange
as well?
 
A

Andrey Tarasevich

Willem said:
) > ...
)> But (c?x:y)=v;
)> I dont really know what to say.
)
) Is there any reason why you believe that the property of "being an
) lvalue" should be necessarily lost in the process of selection from two
) lvalues of the same type?
)
) I mean I'm OK personally with the way it works in C. I just like to know
) what is it exactly in '(c?x:y)=v' that triggers a "I don't really know
) what to say" reaction from some people.

Well then why not also make it possible for functions (that return
pointers) to be lvalues ?

returnspointertostruct(foo)->bar = baz;

Or is that already legal ?

This is perfectly legal. It's just that has nothing to do with the
function. Function still returns a non-lvalue. The left-hand side
expression though

(non-lvalue pointer)->bar

is an lvalue. This why you can assign to it.

What's illegal is this

returnsstruct(foo).bar = baz;

i.e. function returns a 'struct' in this case .
 
R

Richard Tobin

I mean I'm OK personally with the way it works in C. I just like to
know what is it exactly in '(c?x:y)=v' that triggers a "I don't really
know what to say" reaction from some people.
[/QUOTE]
because its not a macro? it returns a value. I dont know the legalise
words but it seems "obvious" enough to me, but again it might be because
I am tainted.

Some other languages allow this. For example, I think Algol 68 allows

IF a THEN b ELSE c FI := d;

In C the number of contexts where an lvalue doesn't decay into an rvalue
is very small, but I don't see anything inherently un-C-like about this
case.

-- Richard
 
R

Richard

Andrey Tarasevich said:
Richard said:
because its not a macro? it returns a value. I dont know the legalise
words but it seems "obvious" enough to me, but again it might be because
I am tainted.

Well, unary '*' operator is also not a macro. Yet it evaluates to an
lvalue. Same for '[]' operator (by definition). Do you find this
strange as well?

I think you have lost the track with all due respect. His original did
produce an lvalue but a value.

The "*" made it then an lvalue in the other case.

I dont really know what we are aguing.

There appears to be some sort of push for ?: to return an lvalue but it
doesnt and never did.
 
R

Richard

because its not a macro? it returns a value. I dont know the legalise
words but it seems "obvious" enough to me, but again it might be because
I am tainted.

Some other languages allow this. For example, I think Algol 68 allows

IF a THEN b ELSE c FI := d;

In C the number of contexts where an lvalue doesn't decay into an rvalue
is very small, but I don't see anything inherently un-C-like about this
case.

-- Richard[/QUOTE]

And he can do it in C using pointers and *. I dont see the problem or
the confusion here as far as the C language goes to be honest.
 
A

Andrey Tarasevich

Richard said:
Richard said:
...
I mean I'm OK personally with the way it works in C. I just like to
know what is it exactly in '(c?x:y)=v' that triggers a "I don't really
know what to say" reaction from some people.
because its not a macro? it returns a value. I dont know the legalise
words but it seems "obvious" enough to me, but again it might be because
I am tainted.
Well, unary '*' operator is also not a macro. Yet it evaluates to an
lvalue. Same for '[]' operator (by definition). Do you find this
strange as well?

I think you have lost the track with all due respect. His original did
produce an lvalue but a value.

The "*" made it then an lvalue in the other case.

I dont really know what we are aguing.

I'm not really arguing. The way I interpreted your responses, it seemed
that when someone said that in C++ '?:' would return an lvalue in this
case, you essentially made it clear that you find it unnatural and/or
illogical (again, the way I interpreted your responses). I just want to
know what is it exactly that you find unnatural and/or illogical.
 
R

Richard Tobin

Well, unary '*' operator is also not a macro. Yet it evaluates to an
lvalue. Same for '[]' operator (by definition). Do you find this
strange as well?
[/QUOTE]
I think you have lost the track with all due respect. His original did
produce an lvalue but a value.

I think the point was that * is an example of an operator that produces
an lvalue, so it's not necessarily unreasonable for the ?: operator to.

-- Richard
 

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
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top