Reputation: 669
Why
(a?b:c)=5;
in 'C' shows lvalue required while
*(a?&b:&c)=5;
is perfectly fine? What is the difference between the two?
Assuming a=1, for first case, it gives b=5 and second case it gives, *(&b)=5
.`
What i am not able to understand is: what difference does it make if we write b=5
or *(&b)=5
?
Upvotes: 0
Views: 154
Reputation: 474436
what difference does it make if we write b=5 or *(&b)=5?
The second one gets a pointer to b
and then dereferences that pointer, storing 5 into the obtained pointer.
However, your question seems to be ignoring the real question: why it works in the second case but not the first. And that has to do with expressions in C and how they're dealt with.
The result of the ?:
operator is a value; specifically, it is an rvalue. Loosely defined, an rvalue is a value that can't go on the left-hand side of an assignment. They are so named because they're values that go on the right-hand side of an assignment. For example, the expression "5" is an rvalue expression. You can't do 5 = 40;
that's nonsense.
A named variable is an lvalue. You can put an lvalue on the left-hand side of an equation. The expression a
is an lvalue expression (assuming that a
is a variable name that is in scope).
However, the expression (a + b)
is an rvalue expression, not an lvalue. And with good reason; you can no more do (a + b) = 30;
than you could (5 + 10) = 30;
.
The result of the ?:
operator is an rvalue expression, just as with the +
operator above. This explains why (a?b:c) = 5;
doesn't work; you're trying to assign a value to an rvalue expression. That's illegal.
Now, let's look at the second case. We know that ?:
results in an rvalue expression. Now, that explains what the classification of the expression is, but what about the type of the expression's result? Well, assuming that b
and c
are both int
s, the type of (a?b:c)
is also int
.
However, when you do (a?&b:&c)
, the type of this expression is int*
, not int
. It is a pointer to an integer. It's an rvalue expression of type "pointer to int
." It will return either the address of b
, or the address of c
.
When you have an int*
, and you dereference it with the *
operator, what do you get? You get an lvalue expression of type int
. Since (a?&b:&c)
is an rvalue expression of type int*
, if you dereference it, you will get an lvalue expression of type int
. This lvalue will refer to either b
or c
, depending on the contents of a
.
To put it simply, it works exactly like this:
int *ptr = NULL;
if(a)
ptr = &b;
else
ptr = &c;
*ptr = 5;
You get a pointer, which could point to any particular memory location, then you store something in the location being pointed to. It's that simple.
Upvotes: 6