address of function's return value

P

Pietro Cerutti

Hi group,

assume the following declarations:

char *func_1(void);
void func_2(char **);

I am allowed to do:

char *c = func_1();
func_2(&c);

But trying to do:

func_s(&(func_1()));

gives "invalid lvalue in unary ‘&’".

If the call "func_1()" is evaluated as a pointer to char, why can't I
access to its address directly?

Thanks
 
P

Pietro Cerutti

Pietro said:
Hi group,

assume the following declarations:

char *func_1(void);
void func_2(char **);

I am allowed to do:

char *c = func_1();
func_2(&c);

But trying to do:

func_s(&(func_1()));

Typo:
func_2(&(func_2()));
 
R

Richard Heathfield

Pietro Cerutti <gahr_AT_gahr_DOT_ch_DO_NOT_SPAM> said:

If the call "func_1()" is evaluated as a pointer to char, why can't I
access to its address directly?

Because it's an rvalue, not an lvalue. You have to store it into an object
before you can take the address of the object.

The following analogy may help you to understand this more clearly. You can
do this:

int i = 6;
foo(&i);

but not this:

foo(&6);

HTH. HAND.
 
P

Pietro Cerutti

Richard said:
Pietro Cerutti <gahr_AT_gahr_DOT_ch_DO_NOT_SPAM> said:



Because it's an rvalue, not an lvalue. You have to store it into an object
before you can take the address of the object.

The following analogy may help you to understand this more clearly. You can
do this:

int i = 6;
foo(&i);

but not this:

foo(&6);

HTH. HAND.

Uhm.. I've heard about lvalues and rvalues many times, but never found a
clear description of their meaning, let alone "rvalue is at the right of
an expression, lvalue is at the left", which isn't really explanatory by
itself..

Anyway, it's clear.. thank you!
 
M

Martin Wells

Pietro:
Uhm.. I've heard about lvalues and rvalues many times, but never found a
clear description of their meaning, let alone "rvalue is at the right of
an expression, lvalue is at the left", which isn't really explanatory by
itself..

Anyway, it's clear.. thank you!

Basically an L-value is something that you can assign to, and an R-
value is something you CANNOT assign to. (Or then again some other
people may say that if something qualifies as an L-value, that it is
also an R-value, but I think the convention is that an L-value is only
an L-value and an R-value is only an R-value).

Of course, there's a little spanner thrown into the works with:

int const x = 5;

x = 7; /* Error */

I suppose you could call x a non-modifiable L-value.

The idea of it all is that an L-value expression is something that can
be changed, an object or variable.

You could have the following:

int *Func(void)
{
static int x = 7;

return &x;
}

int main(void)
{
*Func() = 7;
}

The pointer returned from Func is an R-value, but when the pointer is
dereferenced it yields an L-value.

Martin
 
B

Ben Bacarisse

Martin Wells said:
Pietro:


Basically an L-value is something that you can assign to, and an R-
value is something you CANNOT assign to. (Or then again some other
people may say that if something qualifies as an L-value, that it is
also an R-value, but I think the convention is that an L-value is only
an L-value and an R-value is only an R-value).

Of course, there's a little spanner thrown into the works with:

int const x = 5;

x = 7; /* Error */

I suppose you could call x a non-modifiable L-value.

Indeed I would suggest one does exactly that! The standard certainly
talks about modifiable lvalues.

Another spanner is an array. In C one can't assign to an array but it
is, by the standard's definition, an lvalue.
 
L

lovecreatesbea...

address of function's return value

The value of the expression of a function call may not be stored in
memory automatically, it also can be discarded.
 
K

Keith Thompson

Pietro Cerutti said:
Uhm.. I've heard about lvalues and rvalues many times, but never found a
clear description of their meaning, let alone "rvalue is at the right of
an expression, lvalue is at the left", which isn't really explanatory by
itself..

Anyway, it's clear.. thank you!

If you think it's clear, then I suspect you don't really understand
it. :cool:}

An lvalue is an expression that (potentially) designates an object.
I added the word "potentially" because of cases like this:

int *ptr = NULL;

The expression '*ptr' is an lvalue even if it doesn't *currently*
designate an object, because the lvalue-ness of an expression must be
determinable at compile time.

Unfortunately, the C90 and C99 standards both messed up the definition
of "lvalue". The C90 standard says that an lvalue is an expression
that designates an object. Taken literally, this meant that '*ptr'
either is or is not an lvalue depending on the current value of 'ptr',
which clearly is not what was intended.

The C99 standard attempted to fix this by saying that an lvalue is "an
expression with an object type or an incomplete type other than void;
if an lvalue does not designate an object when it is evaluated, the
behavior is undefined". Taken literally this implies that 42 is an
lvalue, and evaluating it invokes undefined behavior.

As for rvalues, the standard doesn't use the term except in one footnote:

What is sometimes called "rvalue" is in this International
Standard described as the "value of an expression".

The *original* meaning of "lvalue" was different. C says an lvalue is
a kind of expression. In the original pre-C meaning, an lvalue is a
result of evaluating an expression. Evaluating an expression for its
lvalue means determining what object it designates (this is possible
only if the expression actually designates an object). Evaluating an
expression for its rvalue means determining the value of the
expression.
 
R

Richard Tobin

lvalues refer to locations in memory.
[/QUOTE]
Nope

register int m=7;

Who'd have though I'd be criticising Jacob for pedantry?

Even if it's not strictly true that an lvalue is a location in memory,
it conveys the essence of the concept: it's something you can store
things into, rather than just a value.

And if you really want pedantry, registers are a kind of memory.

-- Richard
 
K

Keith Thompson

Old Wolf said:
lvalues refer to locations in memory.

lvalues (potentially) refer to objects.

register int r;
int *p = NULL;

'r' and '*p' are both lvalues.
 
J

jacob navia

Nope

register int m=7;

Who'd have though I'd be criticising Jacob for pedantry?

Even if it's not strictly true that an lvalue is a location in memory,
it conveys the essence of the concept: it's something you can store
things into, rather than just a value.

And if you really want pedantry, registers are a kind of memory.

-- Richard
[/QUOTE]

Yes; registers are some kind of memory. Just not memory locations.

I had an attack of pedantry. I apologize.

I guess I should go to sleep now
:)

jacob
 
J

Joe Wright

Keith said:
lvalues (potentially) refer to objects.

register int r;
int *p = NULL;

'r' and '*p' are both lvalues.
No. p is the lvalue, now NULL. Expressing *p while (p == NULL) is a no
no. If p eventually holds the address of an int object in memory, then
*p will be an lvalue.
 
R

Richard Heathfield

Richard Tobin said:
Nope

register int m=7;

Who'd have though I'd be criticising Jacob for pedantry?[/QUOTE]

Please don't do that. He is right for a change. Let's applaud that. In
fact, somebody break out the champagne, the flags, and those little pastry
things with unspeakable green bits! It's party time! Jacob Navia actually
got something right! This day will go down in history!

If it happens again, do let me know. (I won't hold my breath, though.)
Even if it's not strictly true that an lvalue is a location in memory,
it conveys the essence of the concept: it's something you can store
things into, rather than just a value.

You don't need to use the word "memory" to convey that concept, though.
And if you really want pedantry, registers are a kind of memory.

True, but if you're going to get into which "kind of memory", you need to
be more specific. Clearly, you can't use "lvalue" to refer to locations in
read-only memory, for example.
 
K

Keith Thompson

Joe Wright said:
No. p is the lvalue, now NULL. Expressing *p while (p == NULL) is a no
no. If p eventually holds the address of an int object in memory, then
*p will be an lvalue.

No, '*p' is an lvalue, regardless of the value of p. ('p' is also an
lvalue, but that's beside the point). But using '*p' in a context
that requires an lvalue invokes undefined behavior.

The lvalue-ness of an expression cannot depend on the run-time value
of any object. There are contexts that require lvalues, and the
determination of whether something is an lvalue must be made at
compilation time, since the failure to provide an lvalue is a
constraint violation, requiring a compile-time diagnostic.

For example:

int *p;
/* ... */
*p = 42;

The assignment is legal (not a constraint violation) because '*p' is
an lvalue (specifically a modifiable lvalue) regardless of what the
value of 'p' happens to be. If '*p' does not designate an object when
the assignment is evaluated (e.g., if p == NULL), the behavior is
undefined.

I can't provide chapter and verse, because the standard gets this
wrong. (This isn't just a disgreement; the wording in the standard
leads to logical contradictions.)

The C90 standard got this wrong by implying that lvalue-ness can
depend on run-time values. The C99 standard corrected that problem,
but went too far in the other direction, saying that any expression of
object type is an lvalue.
 
P

pete

Joe said:
No. p is the lvalue, now NULL. Expressing *p while (p == NULL) is a no
no. If p eventually holds the address of an int object in memory, then
*p will be an lvalue.

*p is still an lvalue, just like array[-1].

(*p) has object type.
 
K

Keith Thompson

Richard Heathfield said:
Richard Tobin said: [...]
Even if it's not strictly true that an lvalue is a location in memory,
it conveys the essence of the concept: it's something you can store
things into, rather than just a value.

You don't need to use the word "memory" to convey that concept, though.

Right, the word "object" works better (and the standard's definition
of "object" uses the term "data storage", not "memory").

I don't think the C standard defines the word "memory", but a quick
search turns up a non-normative example that implies that registers
are not "memory". C99 5.1.2.3p12: "Values are independent of whether
they are represented in a register or in memory."
True, but if you're going to get into which "kind of memory", you need to
be more specific. Clearly, you can't use "lvalue" to refer to locations in
read-only memory, for example.

Sure you can. An expression that designates to an object in read-only
memory can be an lvalue; it just can't be a modifiable lvalue.
 
R

Richard Heathfield

pete said:

Whoops - s/lvalue/modifiable lvalue/

This is one of the stupid consequences of a broken C def of "lvalue". The
whole point of lvalues is that they can be put on the left of an
assignment operator, whereas rvalues cannot (except in an expression which
has an lvalue as its result). By making lvalue's definition overly broad,
they have rendered the term less useful and intuitive.
 

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,681
Members
48,796
Latest member
Greg L.

Latest Threads

Top