Pointer Guide

  • Thread starter Foobarius Frobinium
  • Start date
F

Foobarius Frobinium

Please review this guide for clarity, accuracy, etc. so I can
hopefully compile a very good tutorial on how to use pointers in C,
including advanced topics, that is easy to follow and exposes the
details.

http://thelinuxlink.net/~fingolfin/pointer-guide/

My e-mail address is fake. To really contact me, send mail to:
(e-mail address removed), subtracting the blatant
anti-spam component.

--
I'm so happy
'Cause today I found my friends
They're in my head

-- Kurt Cobain
 
A

Arthur J. O'Dwyer

Please review this guide for clarity, accuracy, etc. so I can
hopefully compile a very good tutorial on how to use pointers in C,
including advanced topics, that is easy to follow and exposes the
details.

http://thelinuxlink.net/~fingolfin/pointer-guide/


Your use of "lvalue" and "rvalue" is slightly non-standard, but
IMO consistent enough. The usual terminology would have it
that an /expression/ /is/ an lvalue or an rvalue, depending on
whether the expression denotes an object with an /address/.
You use "lvalue" to mean /address/, and "rvalue" to mean
/value/. Consistent enough, but irking to pedants.

The HTMLification of the first sample program, the one that
begins '/* vim:ts=4 */', is absolutely unreadable on a white
background (the default in most GUI web browsers). Do not
use light green or cyan text on a white background. Prefer
no coloration, especially since you can't seem to decide on
a consistent scheme: why is 'fprintf' black but 'stdout'
magenta, for example?

HTML could be used to great advantage in the body text of
the tutorial, however. Consider bolding new terms on their
first appearance, to make it easier to skim the large
paragraphs; and I recommend using <tt></tt> or <i></i>
around code snippets in the text such as 'foo' and 'frob'.

The line '/* vim:ts=4 */' is completely unnecessary to
your tutorial, BTW, and will only confuse non-Unix types.
Suggest removing the hard tabs from your HTML source code
as well, since I doubt many browsers can effectively deal
with them. Suggest the use of <pre> to format source code.

Suggest 'return 0;' from 'main'. This is not required
by C99, but is a good practice in both C90 and C99. And
you are supposedly writing to instill good practices in
newbies...

"Therefore, the return type of *bar is int..." Delete
the word "return" from this sentence; operators /yield/
values. Functions /return/. Unary * is not a function,
and thus /returns/ nothing.

"The relevance of them will be revealed yet..." Insert
"not" before "be," of course.

s/interchangably/interchangeably/

"And since char's are one byte in length (at least on
all systems I know)..." 'sizeof(char)' is 1 (byte) by
definition. Whether any particular "system" has a
machine-level concept of "byte" is not relevant to C
programming. But then neither is using actual numbers
to refer to "addresses in RAM," so you'll just have to
pick a wording that will satisfy the pedants. Suggest
simply removing the parenthetical comment.

"...in short it is a data type that is made to
reference other data through its lvalue." Confusing.
Firstly, 'short' is a data type, so you've just majorly
confused the skimmers, who aren't paying much attention
to your grammatical flourishes. Secondly, either your
grammar or your content is wrong in the second half of
that sentence; a pointer is an object which references
other data through its "rvalue" (its /value/), or
equivalently a pointer /contains/ another datum's "lvalue"
(its /address/).

"The data an array accesses cannot be changed.
Therefore they are not pointers." Grammar strikes again!
First, the data accessed by an array *can* be changed;
consider 'arr[0] = 42; arr[0] = 43;'. Secondly, the
data accessed by an array *can* be pointers; consider
'int *arp[10];'. You mean, "An array cannot be changed
to 'point' to other data; therefore arrays are not pointers."

s/syntax sugar/syntactic sugar/

Your HTMLification is screwed up majorly in "Basic
Pointer Arithmetic," where it actually "eats" the 'for'
keyword in your loop. Yet another reason to drop the
colorization.

"When you add a number to a number type, such as an int
or double, you get straight addition. But when you do it on
pointers, the number is automatically multiplied by the size
(in bytes) of the type to which the pointer points." This
is how it's usually explained, true. But your lead-in is
somewhat silly, since you never say what you mean by "straight
addition." Obviously the machine code for adding 1 to a
pointer is different from that for adding 1 to an 'int';
but the machine code for adding 1 to a 'double' is often
*far* more complicated. Yet you call the latter two "straight"
addition! IMO it would make more sense simply to tell the
reader that addition on pointers is /defined/ the way it
is, and let them determine for themselves whether it's
weird or not.

s/deference/dereference/

"...the arithmetic operators take precedence over pointer
[dereference] anyway..." This is just flat-out /wrong/.
Remove it, and the surrounding misdirection.

Finally, although the tutorial is obviously not yet
completed, I must urge you to add material on the []
indirection operator. The reader is currently left thinking
that '*(kochba+i)' is the only way to dereference a pointer.
[On a lighter note, I must say I've never seen 'kochba' used
as the third element of 'foo, bar,...'! Very... quirky.]


HTH,
-Arthur
 
F

Foobarius Frobinium

"...the arithmetic operators take precedence over pointer
[dereference] anyway..." This is just flat-out /wrong/.
Remove it, and the surrounding misdirection.

They don't?? I woulda sworn they did...damn, I'll have to check. Maybe
something is wrong with gcc, but maybe I was just being stupid
Finally, although the tutorial is obviously not yet
completed, I must urge you to add material on the []
indirection operator. The reader is currently left thinking
that '*(kochba+i)' is the only way to dereference a pointer.
[On a lighter note, I must say I've never seen 'kochba' used
as the third element of 'foo, bar,...'! Very... quirky.]

Yes, the very next thing I was planning was how the [] form works, and
tie that back into the equivalency of arrays and pointers. As for
'kochba', any Jewish hackers you might know might be able to tell you
of Simeon Bar Kochba, who invented subsurface operations as an element
of guerilla warfare (i.e., Whack-A-Guerilla), 1800 years before Dien
Bien Phu. It's true!

Quirkiness in amidst hopefully useful data is all part of my
adolescent inanities, and probably makes the reading a little easier.
 
J

Jack Klein

Please review this guide for clarity, accuracy, etc. so I can
hopefully compile a very good tutorial on how to use pointers in C,
including advanced topics, that is easy to follow and exposes the
details.

http://thelinuxlink.net/~fingolfin/pointer-guide/

My e-mail address is fake. To really contact me, send mail to:
(e-mail address removed), subtracting the blatant
anti-spam component.

I disagree with Arthur. You have this in the first paragraph:

"The lvalue is the variable's address in memory, and the rvalue is the
actual content of the variable."

You completely misunderstand the concepts of lvalues and rvalues in C.

In the snippet:

int x;
x = 3;

....the integer constant literal '3' is an rvalue that has nothing at
all to do with any variable.

The C standard defines the term 'lvalue' in part of a single sentence:

"An lvalue is an expression with an object type or an incomplete type
other than void" [6.3.2.1 P. 1]

Notice that the neither of the words 'address' or 'variable' appear in
this definition.

Also note that the C standard has dropped the word 'rvalue' from the
official terms of the language. It is mentioned only in a footnote:

"What is sometimes called ‘‘rvalue’’ is in this International Standard
described as the ‘‘value of an expression’’" [Footnote 53]

Just a little bit later, in your second sentence, you say:

"A pointer is a variable whose rvalue is the lvalue of another
variable."

This is just plain wrong. The value of a pointer object is an
'address'. A pointer object itself is an lvalue. The address that it
contains is not any sort of lvalue. Performing a dereference on a
pointer (other than pointer to void) creates an expression with an
object type, so *p is an lvalue expression.

Saying that the value of a pointer is an lvalue is like saying that
the value of an int is an lvalue.

Consider:

int x = 3;

....'x' is an lvalue, and has the value 3.

Now let's add:

int *ip = &x;

....'*ip' is an lvalue, which is an expression of object type (type
int) with the value of 'x', namely 3.

....'ip' is an lvalue, an expression of object type (type pointer to
int) with the value address of 'x'.

But the contents of 'ip', namely the address of x, is not an lvalue,
anymore than the contents of 'x', namely the integer value 3, is.

Have you actually obtained and read a copy of the ISO C Standard? The
PDF version is available for $18.00 US from ANSI. Until you do, I
seriously suggest you stop trying to write about things like lvalues
and rvalues, because you do not know their actual definitions and the
result is just plain incorrect.
 
M

Mark Richards

Jack,

I was very interested in reading this Pointer Guide, since I need a few.
Perhaps I should stick to K&R for now, but I'm tempted to give this a
read. Would it lead me too far astray?

I noticed on your web page http://jk-technology.com/c/standards.html#c99
that you mention a new book was in process by Dr. Bjarne Stroustrup. Do
you happen to know if it has been published yet, and if so by whom?

Mark Richards
 
O

Old Wolf

Jack Klein said:
In the snippet:

int x;
x = 3;

...the integer constant literal '3' is an rvalue that has nothing at
all to do with any variable.

The C standard defines the term 'lvalue' in part of a single sentence:

"An lvalue is an expression with an object type or an incomplete type
other than void" [6.3.2.1 P. 1]

'3' is an expression, it has type "int", and an int is an object,
therefore it is an expression with an object type. So your quote
seems to say that '3' is an lvalue. Where have I gone wrong..
 
T

tweak

Mark said:
Jack,

I was very interested in reading this Pointer Guide, since I need a few.
Perhaps I should stick to K&R for now, but I'm tempted to give this a
read. Would it lead me too far astray?

I noticed on your web page http://jk-technology.com/c/standards.html#c99
that you mention a new book was in process by Dr. Bjarne Stroustrup. Do
you happen to know if it has been published yet, and if so by whom?

Mark Richards

The two places I learned pointers were:

1) K&R2

and

2) A Tutorial on Pointers and Arrays in C by Ted Jensen (which is like
reading K&R2 with expanded examples). The last url I have for this
document is: http://pweb.netcom.com/~tjensen/ptr/cpoint.htm

And thanks to all the folks here who helped me with restrict.

Cheers,

Brian
 
M

Mark McIntyre

Jack Klein said:
In the snippet:

int x;
x = 3;

...the integer constant literal '3' is an rvalue that has nothing at
all to do with any variable.

The C standard defines the term 'lvalue' in part of a single sentence:

"An lvalue is an expression with an object type or an incomplete type
other than void" [6.3.2.1 P. 1]

'3' is an expression, it has type "int", and an int is an object,
therefore it is an expression with an object type. So your quote
seems to say that '3' is an lvalue.

if '3' were an lvalue, you could put it on the left of an expression
3 = x+2;
so you know your interpretation is wrong. <aside>this is a slight
exaggeration said:
Where have I gone wrong..

You have applied "all ducks have feet, therefore all feet belong to ducks"
logic.

Because an object can have type int, it does not follow that all things of
type int are objects. You can have constants of type int. A constant need
not be a region of data storage, it could be built into the machine code of
the program (and often is).
 
X

xarax

Mark McIntyre said:
Jack Klein said:
In the snippet:

int x;
x = 3;

...the integer constant literal '3' is an rvalue that has nothing at
all to do with any variable.

The C standard defines the term 'lvalue' in part of a single sentence:

"An lvalue is an expression with an object type or an incomplete type
other than void" [6.3.2.1 P. 1]

'3' is an expression, it has type "int", and an int is an object,
therefore it is an expression with an object type. So your quote
seems to say that '3' is an lvalue.

if '3' were an lvalue, you could put it on the left of an expression
3 = x+2;
so you know your interpretation is wrong. <aside>this is a slight
exaggeration said:
Where have I gone wrong..

You have applied "all ducks have feet, therefore all feet belong to ducks"
logic.

Because an object can have type int, it does not follow that all things of
type int are objects. You can have constants of type int. A constant need
not be a region of data storage, it could be built into the machine code of
the program (and often is).

I just use a very naive definition that seems to
work for me in most cases:

1. "lvalue"; the "l" (lower case ell) means "left". It's
something that can appear on the left side of an assignment.

2. "rvalue"; the "r" means "right". It's something that
can *only* appear on the right side of an assignment (an
expression that doesn't satisfy the requirements for lvalue).

The compiler will tell me when I get it wrong. That's
good enough for me.


--
----------------------------
Jeffrey D. Smith
Farsight Systems Corporation
24 BURLINGTON DRIVE
LONGMONT, CO 80501-6906
http://www.farsight-systems.com
z/Debug debugs your Systems/C programs running on IBM z/OS for FREE!
 
R

Ralmin

Old Wolf said:
'3' is an expression, it has type "int", and an int is
an object, therefore it is an expression with an object
type. So your quote seems to say that '3' is an lvalue.
Where have I gone wrong..

You went wrong where you said an int is an object. Expressions of type int
do not necessarily refer to objects.

An integer constant between -32767 and 32767 is guaranteed to be of type
int. An integer constant from -2147483647 to -32768, or from 32768 to
2147483647 is guaranteed to be of type int if it fits in an int, otherwise
of type long.

An exception: Take as an example the expression -32768, which is actually
the integer constant 32768 which is then negated. Consider a 2's complement
system where int is 16 bits. Because the value of positive 32768 does not
fit into an int, it is given type long. Then, when negated, it still has
type long despite that the value now does fit into an int.

On Borland's Turbo C (a 16-bit MS-DOS compiler):
sizeof(-32768) == 4
sizeof(-32767-1) == 2
 
O

Old Wolf

xarax said:
I just use a very naive definition that seems to
work for me in most cases:

1. "lvalue"; the "l" (lower case ell) means "left". It's
something that can appear on the left side of an assignment.

2. "rvalue"; the "r" means "right". It's something that
can *only* appear on the right side of an assignment (an
expression that doesn't satisfy the requirements for lvalue).

The compiler will tell me when I get it wrong. That's
good enough for me.

That isn't much of a 'definition'. In fact it's wrong: the name
of an array is an lvalue but it can't appear on the left side of
an assignment. Your definition is circular, ie. it doesn't help
one whit in determining whether an expression is an lvalue or not.
The standard says that an assignment consists of
(modifiable-lvalue) = (expression)
.. This depends on modifiable-lvalue already being defined.

Your 'definition' is better called 'empirical method for determining',
and has another problem in that many compilers allow assignments to
non-lvalues in some cases.
 
C

Chris Dollin

Old said:
That isn't much of a 'definition'.

It's pretty nearly *the* definition (apart from the "only"); the
lvalue is what you get when you evaluate as per the lhs of an
expression, the rvalue is what you get when you evaluate as per the
rhs. That's what Strachey meant when he introduced the terms. All
the nitpickery is just formalising it, usually for specific languages.

Of course for languages like Pop11 the terminology breaks down
somewhat ...

[Pop assignments run left-to-right, eg `42 -> x`, and the notion of
`lvalue` is not so much `address` as `procedure`, since the target
can be a procedure call eg `17 -> hd(someList)`.]
 
J

Jeremy Yallop

Old said:
Jack Klein said:
The C standard defines the term 'lvalue' in part of a single sentence:

"An lvalue is an expression with an object type or an incomplete type
other than void" [6.3.2.1 P. 1]

'3' is an expression, it has type "int", and an int is an object,
therefore it is an expression with an object type. So your quote
seems to say that '3' is an lvalue.

I think that's basically correct according to the wording of the
standard (although you should perhaps change "and an int is an object"
to "and int is an object type").

The notion of "lvalue", while intuitively pretty clear, seems
surprisingly difficult to pin down satisfactorily. In K&R 1 "lvalue"
was defined by the grammar, so "lvalueness" could be determined during
the earliest stages of compilation.

(something like)

lvalue ::= identifier
* identifier
expression[expression]
( lvalue )

The first C standard ("C89") introduced a new definition of "lvalue"
that postponed the decision as to whether a particular expression is
an lvalue until runtime:

An lvalue is an expression (with an object type or an incomplete
type other than void) that designates an object.

Consider the program

int main(int argc, char **argv)
{
argv[2];
}

Does the expression argv[2] "designate an object"? The answer depends
on the arguments passed to the program, so in some runs of the program
the expression is an lvalue, and in some it is not (and invokes
undefined behaviour by attempting to access elements outside of the
array).

The last C standard ("C99") changed the definition yet again to the
wording Jack quoted above:

An lvalue is an expression with an object type or an incomplete type
other than void

For better or worse, the effect has been to move the test for
"lvalueness" to somewhere between where the previous definitions
placed it: to the time when types are associated with expressions and
checked for consistency. In C99 whether a particular expression is an
lvalue -- i.e. whether it is an "expression with an object type"
&c. -- cannot be determined by the BNF grammar, because the grammar
contains no information about types. Further, unlike in C89, there is
no need to wait until runtime, because, C being "statically typed",
the type of every expression in C is determined during translation.
As a result, the expression "argv[2]" in the program above, which is
/sometimes/ an lvalue under the C89 definition, is /always/ an lvalue
according to the C99 rules.

A side effect, then, of the new definition is that certain expressions
that do not always refer to objects -- and some which never do -- are
now considered lvalues. Unfortunately, the new wording appears to be
a little too broad, and now encompasses expressions which not only
/do/ not refer to objects (which was an unavoidable consequence of
moving the "lvalueness test" from runtime to translation-time), but
which /cannot/ (e.g. the integer literal '3' in your example).

Jeremy.
 
D

Dan Pop

In said:
Jack Klein said:
In the snippet:

int x;
x = 3;

...the integer constant literal '3' is an rvalue that has nothing at
all to do with any variable.

The C standard defines the term 'lvalue' in part of a single sentence:

"An lvalue is an expression with an object type or an incomplete type
other than void" [6.3.2.1 P. 1]

'3' is an expression, it has type "int", and an int is an object,
therefore it is an expression with an object type. So your quote
seems to say that '3' is an lvalue. Where have I gone wrong..

Nowhere. 3 *is* an lvalue in C99, period. The C89 definition was

An lvalue is an expression (with an object type or an incomplete
type other than void) that designates an object.

Which was simple, clear and made sense.

The full C99 version is:

1 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.

Which is actually the traditional definition of rvalue! It's still simple
and clear, it just doesn't make any sense ;-)

The practical implications are insignificant, however, as the standard
is carefully written to overrule the usage of 3 in any place where a C89
lvalue is actually required. And if the committee forgot to fix
the wording to match the new definition in one place or another,
undefined behaviour is covering the effects of the mistake ;-)

Dan
 
O

Old Wolf

Jeremy Yallop said:
Old said:
Jack Klein said:
The C standard defines the term 'lvalue' in part of a single sentence:

"An lvalue is an expression with an object type or an incomplete type
other than void" [6.3.2.1 P. 1]

'3' is an expression, it has type "int", and an int is an object,
therefore it is an expression with an object type. So your quote
seems to say that '3' is an lvalue.

I think that's basically correct according to the wording of the
standard (although you should perhaps change "and an int is an object"
to "and int is an object type").

A side effect, then, of the new definition is that certain expressions
that do not always refer to objects -- and some which never do -- are
now considered lvalues. Unfortunately, the new wording appears to be
a little too broad, and now encompasses expressions which not only
/do/ not refer to objects (which was an unavoidable consequence of
moving the "lvalueness test" from runtime to translation-time), but
which /cannot/ (e.g. the integer literal '3' in your example).

Just after that quote (in N869 at least) is:

A modifiable lvalue is an lvalue that does not
have array type, does not have an incomplete type, does not
have a const-qualified type, and if it is a structure or
union, does not have any member (including, recursively, any
member or element of all contained aggregates or unions)
with a const-qualified type.

'3' has type "int" (not "int const"). So '3' is actually a modifiable
lvalue. The only constraint on the left-operand of an assignment
(or the operand of ++ or --) is that it is a modifiable lvalue.

So I guess this means that a C99 conforming compiler doesn't have to
issue any diagnostic for:
3++;
or
3 = 4;
 
J

J. J. Farrell

Mark McIntyre said:
Jack Klein said:
In the snippet:

int x;
x = 3;

...the integer constant literal '3' is an rvalue that has nothing at
all to do with any variable.

The C standard defines the term 'lvalue' in part of a single sentence:

"An lvalue is an expression with an object type or an incomplete type
other than void" [6.3.2.1 P. 1]

'3' is an expression, it has type "int", and an int is an object,
therefore it is an expression with an object type. So your quote
seems to say that '3' is an lvalue.

if '3' were an lvalue, you could put it on the left of an expression
3 = x+2;
so you know your interpretation is wrong. <aside>this is a slight
exaggeration said:
Where have I gone wrong..

You have applied "all ducks have feet, therefore all feet belong to ducks"
logic.

Because an object can have type int, it does not follow that all things of
type int are objects. You can have constants of type int. A constant need
not be a region of data storage, it could be built into the machine code of
the program (and often is).

I think Old Wolf is right here. Mark's talking Common Sense whereas
Old Wolf is talking The Standard - they often do not go together.

C89 is clear that an lvalue designates an object. This has been
changed in C99, and I doubt very much that it is supposed to mean
what it appears to say.

6.3.2.1 Lvalues, arrays, and function designators

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.

It seems clear that an expression such as 3+5 is an lvalue, since
it is an expression with an object type (as opposed to a function
type or an incomplete type, those being the three types of type
in C99). It also seems clear that

int i;

i = 3+5;

results in undefined behaviour, since it involves the evaluation
of an lvalue that does not designate an object.

I'm sure this isn't what the Standardizers meant, but it appears
to be what they've said. Can anyone show otherwise?
 
I

Irrwahn Grausewitz

(e-mail address removed) (J. J. Farrell) wrote:

[about lvalues and rvalues]
C89 is clear that an lvalue designates an object. This has been
changed in C99, and I doubt very much that it is supposed to mean
what it appears to say.

6.3.2.1 Lvalues, arrays, and function designators

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.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It seems clear that an expression such as 3+5 is an lvalue, since
it is an expression with an object type (as opposed to a function
type or an incomplete type, those being the three types of type
in C99).

While 3+5 is indeed an lvalue, it cannot legitimately be used as
such: it doesn't designate an object (in simple terms: you cannot
take its address). Remember: an expression that has object type
does not necessarily designate an object as well.
It also seems clear that

int i;

i = 3+5;

results in undefined behaviour, since it involves the evaluation
of an lvalue that does not designate an object.

Wrong. Of course the lvalue i designates an object, specifically
the one at the memory location &i.
I'm sure this isn't what the Standardizers meant, but it appears
to be what they've said. Can anyone show otherwise?

You missed C99 6.3.2.1p2:

2 Except when it is the operand of the sizeof operator, the unary &
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
operator, the ++ operator, the -- operator, or the left operand of
the . operator or an assignment operator, an lvalue that does not
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
have array type is converted to the value stored in the designated
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
object (and is no longer an lvalue).
^^^^^^

Hence, in i = 3+5; the left hand operand of the assignment operator
is *not* evaluated for the value, but for the designator.

Regards
 
I

Irrwahn Grausewitz

Jack Klein said:
In the snippet:

int x;
x = 3;

...the integer constant literal '3' is an rvalue that has nothing at
all to do with any variable.

The C standard defines the term 'lvalue' in part of a single sentence:

"An lvalue is an expression with an object type or an incomplete type
other than void" [6.3.2.1 P. 1]

'3' is an expression, it has type "int", and an int is an object,

No; int is a type.

That's correct. The expression 3 has the object type int, albeit it
does not designate an object. All objects are of object type, but not
all expressions with an object type designate objects as well.
Nowhere. 3 *is* an lvalue in C99, period.

Agreed, but one that invokes undefined behaviour when used as such,
as per C99 6.3.2.1p1: "[...] if an lvalue does not designate an
object when it is evaluated, the behavior is undefined."
The C89 definition was

An lvalue is an expression (with an object type or an incomplete
type other than void) that designates an object.

Which was simple, clear and made sense.

The full C99 version is:

1 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.

Which is actually the traditional definition of rvalue!

I beg to disagree, since evaluation rvalues that do not designate
objects doesn't invoke undefined behaviour.
It's still simple
and clear, it just doesn't make any sense ;-)

Because it is incomplete: you omitted the evaluation rules in
6.3.2.1p2, which is the second part of the lvalue definition:

2 Except when it is the operand of the sizeof operator, the unary
& operator, the ++ operator, the -- operator, or the left
operand of the . operator or an assignment operator, an lvalue
that does not have array type is converted to the value stored
in the designated object (and is no longer an lvalue). If the
lvalue has qualified type, the value has the unqualified version
of the type of the lvalue; otherwise, the value has the type of
the lvalue. If the lvalue has an incomplete type and does not
have array type, the behavior is undefined.
The practical implications are insignificant, however, as the standard
is carefully written to overrule the usage of 3 in any place where a C89
lvalue is actually required.

Ideed, see quote above.

<snip>

Regards
 
D

Dan Pop

In said:
I beg to disagree, since evaluation rvalues that do not designate
objects doesn't invoke undefined behaviour.

The *definition* stops at the semicolon.

Dan
 
K

kal

Nowhere. 3 *is* an lvalue in C99, period.

It does not seem to me to be what the standard implies.
The C89 definition was

An lvalue is an expression (with an object type or an incomplete
type other than void) that designates an object.

Which was simple, clear and made sense.

Quite. lvalue is defined to be (a) An expression, and (b) the
value of which DESIGNATES an object. They key word here is
DESIGNATES.
The full C99 version is:

1 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.

This is precisely the same as the C89 definition, viz., an lvalue
is (a) an expression and, (b) the value of which must DESIGNATE
an object.

I am not in possession of a copy of the C99 standard. But in one
of the drafts of it the following are stated.

6.3.2.1 Lvalues and function designators

1 An lvalue is an expression with an object type or an incomplete
type other than void;(44) if an lvalue does not designate an
object when it is evaluated, the behavior is undefined. When an
object is said to have a particular type, the type is specified
by the lvalue used to designate the object. A modifiable lvalue
is an lvalue that does not have array type, does not have an
incomplete type, does not have a const-qualified type, and if it
is a structure or union, does not have any member (including,
recursively, any member or element of all contained aggregates
or unions) with a const-qualified type.

The footnote (44) provides some additional information.

(44) The name ‘‘lvalue'' comes originally from the assignment
expression E1 = E2, in which the left operand E1 is
required to be a (modifiable) lvalue. It is perhaps better
considered as representing an object ‘‘locator value''.
What is sometimes called ‘‘rvalue'' is in this International
Standard described as the ‘‘value of an expression''.

An obvious example of an lvalue is an identifier of an
object. As a further example, if E is a unary expression
that is a pointer to an object, *E is an lvalue that
designates the object to which E points.
 

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

Forum statistics

Threads
474,143
Messages
2,570,822
Members
47,368
Latest member
michaelsmithh

Latest Threads

Top