Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > lvalues and rvalues

Reply
Thread Tools

lvalues and rvalues

 
 
Keith Thompson
Guest
Posts: n/a
 
      04-07-2010
writes:
> Keith Thompson <kst-> wrote:
>> What the standard probably should say is "if an lvalue does not
>> designate an object when it is evaluated *in a context that requires
>> an lvalue*, the behavior is undefined.

>
> Isn't that addition redundant? I can't think of *any* context where an
> lvalue that doesn't desginate an object can be safely evaluated.


Yes, you're right. (I get the feeling this isn't the first time I've
made that mistake.)

The current standard says (C99 6.3.2.1p1):

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.

The second part of the sentence is ok. For example:

int i;
int *ptr = NULL;

i = *ptr;

*ptr is an lvalue, it's being evaluated in a context that doesn't
require an lvalue, and the behavior is undefined because it doesn't
currently designate an object. <OT>(I think the way C++ expresses it
is that it's evaluated as an lvalue, and then an lvalue-to-rvalue
conversion is performed.)</OT>

The real problem is that the first part of the sentence is too broad;
it makes 42 an lvalue, which it clearly is not intended to be.

The C90 standard's definition (an lvalue is an expression ... that
designates an object) was too narrow; it implied that *ptr is an
lvalue if and only if ptr currently contains a valid non-null pointer
value, whereas lvalue-ness needs to be determinable at compile time.

Either an lvalue needs to be defined as an expression that
*potentially* designates an object (defining "potentially" is tricky),
or the definition needs to enumerate the set of expressions that are
lvalues (I think they can be defined syntactically), or it can just
say that an lvalue is an expression whose description in section 6.5
says it's an lvalue.

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
 
Nicklas Karlsson
Guest
Posts: n/a
 
      04-07-2010
"I'd say "address" rather than "starting address". In C, an address
is
typed. It doesn't point to the beginning of an object, it points to
the object."

So since an address is typed, int* for example, one says that it
points to the entire object? It points to an "int", but nevertheless
it still points to the first allocated byte of size(int) bytes
allocated for an int

"No, an lvalue, like any expression, has a type."

I thougt that the result yielded by an expression has a type, not the
expression itself, could you give an example of how an expression has
a type?

"Too many words. An rvalue is the value of an expression, that's all.
It's also a term that the Standard doesn't use, and I see little point
in using it while discussing C. <OT>(C++ is another matter.)</OT>"

OK, but even tho the term is avoided, could I re-sentence and say
something along the lines with: An rvalue is the result (value)
yielded any expression, except if the expression is an lvalue
appearing on LHS?
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      04-07-2010
Nicklas Karlsson <> writes:
> "I'd say "address" rather than "starting address". In C, an address
> is typed. It doesn't point to the beginning of an object, it points
> to the object."
>
> So since an address is typed, int* for example, one says that it
> points to the entire object? It points to an "int", but nevertheless
> it still points to the first allocated byte of size(int) bytes
> allocated for an int


Well, that's one way to look at it, but I find it clearer to think of
an address (pointer value) as pointing to the entire object. It's one
way in which a C pointer value is conceptually different, and at a
higher level, than a machine address.

> "No, an lvalue, like any expression, has a type."
>
> I thougt that the result yielded by an expression has a type, not the
> expression itself, could you give an example of how an expression has
> a type?


An expression has the type of the value that it yields. For example,
the expression ``2 + 2'' is of type int, as does the value, 4, that it
yields.

I'm not 100% certain that the standard expresses it this way, but it
seems reasonable.

> "Too many words. An rvalue is the value of an expression, that's all.
> It's also a term that the Standard doesn't use, and I see little point
> in using it while discussing C. <OT>(C++ is another matter.)</OT>"
>
> OK, but even tho the term is avoided, could I re-sentence and say
> something along the lines with: An rvalue is the result (value)
> yielded any expression, except if the expression is an lvalue
> appearing on LHS?


I suppose so.

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Stefan Ram
Guest
Posts: n/a
 
      04-07-2010
Nicklas Karlsson <> writes:
>"I'd say "address" rather than "starting address". In C, an
>address is typed. It doesn't point to the beginning of an
>object, it points to the object."


int main( void ){ char a[ 9 ]; char * p = a; return !p; }

Above, p »points« to the beginning of the object a.

int main( void ){ char a[ 9 ]; char( *p )[ 9 ]= &a; return !p; }

Above, p indeed points to a.

 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      04-07-2010
On 4/7/2010 5:05 PM, Keith Thompson wrote:
> Nicklas Karlsson<> writes:
>> "I'd say "address" rather than "starting address". In C, an address
>> is typed. It doesn't point to the beginning of an object, it points
>> to the object."
>>
>> So since an address is typed, int* for example, one says that it
>> points to the entire object? It points to an "int", but nevertheless
>> it still points to the first allocated byte of size(int) bytes
>> allocated for an int

>
> Well, that's one way to look at it, but I find it clearer to think of
> an address (pointer value) as pointing to the entire object. It's one
> way in which a C pointer value is conceptually different, and at a
> higher level, than a machine address.


It seems to me that an int* could address any byte of an
int object (maybe even no byte at all), so long as the platform
knows how to get at the entire int given the int* value.
Converting to a char* must produce a pointer to the [0] element
of a sizeof(int)-byte array that overlays the int object, but
that's no obstacle: conversion need not be a bit-for-bit copy.

Here's a challenge: If an int* does *not* address the first
byte of an int object, can a portable[*] program detect the fact?
[*] "Portable" instead of "strictly conforming," because the
output of an S.C. program cannot depend on implementation-defined,
unspecified, or undefined behavior. Since the representation of
an int* value is unspecified, an S.C. program that detected something
about it could not report what it discovered. But let's take an
informal notion of "portable" to mean that we're not allowed to
inspect the bits of the int* itself and try to find the bits of
a char* somewhere inside it. What can a "portable" program do to
show or refute "An int* holds the address of the byte just after
the int object," for example?

--
Eric Sosman
lid
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      04-07-2010
Keith Thompson <kst-> writes:
> Nicklas Karlsson <> writes:

[...]
>> I thougt that the result yielded by an expression has a type, not the
>> expression itself, could you give an example of how an expression has
>> a type?

>
> An expression has the type of the value that it yields. For example,
> the expression ``2 + 2'' is of type int, as does the value, 4, that it
> yields.
>
> I'm not 100% certain that the standard expresses it this way, but it
> seems reasonable.

[...]

In fact the standard does talk about the type of an expression.
Just a few examples:

C99 6.5.1p3:
A constant is a primary expression. Its type depends on its form
and value, as detailed in 6.4.4.

p4:
A string literal is a primary expression. It is an lvalue with
type as detailed in 6.4.5.

p5:
A parenthesized expression is a primary expression. Its type and
value are identical to those of the unparenthesized expression.

6.5.2.1p1:
One of the expressions shall have type ‘‘pointer to object
_type_’’, the other expression shall have integer type, and the
result has type ‘‘_type_’’.
(Underscores denote italics.)

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Phil Carmody
Guest
Posts: n/a
 
      04-07-2010
Keith Thompson <kst-> writes:
> Nicklas Karlsson <> writes:
>> "I'd say "address" rather than "starting address". In C, an address
>> is typed. It doesn't point to the beginning of an object, it points
>> to the object."
>>
>> So since an address is typed, int* for example, one says that it
>> points to the entire object? It points to an "int", but nevertheless
>> it still points to the first allocated byte of size(int) bytes
>> allocated for an int

>
> Well, that's one way to look at it, but I find it clearer to think of
> an address (pointer value) as pointing to the entire object. It's one
> way in which a C pointer value is conceptually different, and at a
> higher level, than a machine address.


Yeah, but no, but yeah, but no, but most architectures have some
kind of indexed indirect addressing mode; so an address register
could be numerically equal to the address of the start of an object,
but used to access the whole object.

And in fact on my alpha, the machine address points to *more*
than the object, if the object is less than 64 bits - char access
requires post-processing to get the single octet desired from the
whole word.

Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
 
Reply With Quote
 
Nicklas Karlsson
Guest
Posts: n/a
 
      04-07-2010
Thanks guys, and a gold star to Keith
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      04-07-2010
Phil Carmody <> writes:
> Keith Thompson <kst-> writes:
>> Nicklas Karlsson <> writes:
>>> "I'd say "address" rather than "starting address". In C, an address
>>> is typed. It doesn't point to the beginning of an object, it points
>>> to the object."
>>>
>>> So since an address is typed, int* for example, one says that it
>>> points to the entire object? It points to an "int", but nevertheless
>>> it still points to the first allocated byte of size(int) bytes
>>> allocated for an int

>>
>> Well, that's one way to look at it, but I find it clearer to think of
>> an address (pointer value) as pointing to the entire object. It's one
>> way in which a C pointer value is conceptually different, and at a
>> higher level, than a machine address.

>
> Yeah, but no, but yeah, but no, but most architectures have some
> kind of indexed indirect addressing mode; so an address register
> could be numerically equal to the address of the start of an object,
> but used to access the whole object.


And an address register might very well contain something that looks
like, and can be operated on as, an integer.

A C pointer value, conceptually at least, does not.

> And in fact on my alpha, the machine address points to *more*
> than the object, if the object is less than 64 bits - char access
> requires post-processing to get the single octet desired from the
> whole word.


--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Phil Carmody
Guest
Posts: n/a
 
      04-07-2010
Eric Sosman <> writes:
> On 4/7/2010 5:05 PM, Keith Thompson wrote:
>> Nicklas Karlsson<> writes:
>>> "I'd say "address" rather than "starting address". In C, an address
>>> is typed. It doesn't point to the beginning of an object, it points
>>> to the object."
>>>
>>> So since an address is typed, int* for example, one says that it
>>> points to the entire object? It points to an "int", but nevertheless
>>> it still points to the first allocated byte of size(int) bytes
>>> allocated for an int

>>
>> Well, that's one way to look at it, but I find it clearer to think of
>> an address (pointer value) as pointing to the entire object. It's one
>> way in which a C pointer value is conceptually different, and at a
>> higher level, than a machine address.

>
> It seems to me that an int* could address any byte of an
> int object (maybe even no byte at all), so long as the platform
> knows how to get at the entire int given the int* value.
> Converting to a char* must produce a pointer to the [0] element
> of a sizeof(int)-byte array that overlays the int object, but
> that's no obstacle: conversion need not be a bit-for-bit copy.
>
> Here's a challenge: If an int* does *not* address the first
> byte of an int object, can a portable[*] program detect the fact?


Sometimes. If the int* compares equal to 0, then it clearly
does not address the first byte of an int object. The answer
can not be 'always', IMHO, as I can't see any way a portable
program can know if a pointer's been freed or not.

Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
casts and lvalues jacob navia C Programming 68 06-27-2007 03:32 PM
cv-qualified rvalues Steven T. Hatton C++ 1 12-14-2006 09:45 PM
Lvalues and Rvalues ramasubramanian.rahul@gmail.com C Programming 3 10-14-2006 09:55 PM
rvalues and constant reference to a pointer ? amparikh@gmail.com C++ 6 06-08-2005 03:19 PM
string literal is an lvalue; other literals are rvalues. Steven T. Hatton C++ 11 04-20-2004 01:38 AM



Advertisments