473,432 Members | 1,414 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,432 software developers and data experts.

gcc: pointer to array

Hi all,

I have a question regarding the gcc behavior (gcc version 3.3.4).

On the following test program it emits a warning:
#include <stdio.h>

int aInt2[6] = {0,1,2,4,9,16};
int aInt3[5] = {0,1,2,4,9};

void print1 (const int* p, size_t cnt)
{
while (cnt--)
printf ("%d\n", *p++);
}

void print2 (const int (*p)[5])
{
size_t cnt;
#if 0
// prohibited:
(*p)[0]=0;
#endif
for (cnt=0; cnt<5; cnt++)
printf ("%d\n", (*p)[cnt]);
}

int main()
{
printf ("test begin\n");

print1 (aInt2, sizeof(aInt2)/sizeof(aInt2[0]));
print2 (&aInt3); // <-- warns here

printf ("test end\n");
return 0;
}

The warning is:
MOD.c: In function `main':
MOD.c:: warning: passing arg 1 of `print2' from incompatible pointer type

Why is that? How is this different from using print1 (aInt2, ...)? All I
want to do is to explicitly show that the pointer is to an array of 5
entries and ensure that it's not modified in anyway inside print2(). However
the #if 0'd assignment operator inside print2() is correctly handled by
gcc -- an error is generated:
MOD.c: In function `print2':
MOD.c:: error: assignment of read-only location
What's wrong with gcc?

There's another thing about the pointer to the array is... The compiler
doesn't generate a warning if I change in print2()
for (cnt=0; cnt<5; cnt++)
to
for (cnt=0; cnt<6; cnt++)
and lets me access (*p)[5], though I think at least a warning should be
generated here.
It doesn't warn me if I put
aInt3[6] = 0;
into main(). But in both cases the compiler "knows" the real size of the
array, still no warning...
Is this OK???

Thanks,
Alex
P.S. I compile it as gcc MOD.c -Wall -oMOD.exe
Nov 15 '05
204 12862
(xpost from alt.os.development)

Thanks! Really a brilliant explanation!

--
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
ma***@storagecraft.com
http://www.storagecraft.com

"Richard Heathfield" <in*****@address.co.uk.invalid> wrote in message
news:db**********@nwrdmz02.dmz.ncs.ea.ibs-infra.bt.com...
[Followups set to comp.lang.c]

Lukaszp wrote:
The problem is that array itself is a pointer to it's beginning so then


Not quite. The array itself is an array. The /value/ of the array, when that
array's name is used in a value context, is the address of the first
element.
writing &aInt3 would give you pointer to pointer to an array. Solution
is to pass only aInt3 to your function.


The declaration in question was:

int aInt3[5] = {0,1,2,4,9};

When you write &aInt3, you're actually getting the address of the array (the
array is not being used in a value context here); the type is int (*)[5],
i.e. a pointer to an array, not a pointer to a pointer to an array as you
incorrectly claimed. (This is a tricky area - it's intensely logical, but
C's logic doesn't always map perfectly to programmers' first-cut instinct!)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
mail: rjh at above domain

Nov 15 '05 #151
pete wrote:
Have you yet noticed that a constant expression like (5),
fits the C99 definition of an Lvalue which does not refer
to an object and causes undefined behavior when evaluated?


I missed your implication that C90's definition is different.

So C90's is too restrictive and C99's too liberal, although the
intended definition is pretty clear.

A useful summary is this Keith Thompson post.

http://groups-beta.google.com/group/...9096173?hl=en&

In future I'll try to search before replying.

Nov 15 '05 #152
Netocrat <ne******@dodo.com.au> wrote:
On Sun, 17 Jul 2005 20:25:35 +0000, S.Tobias wrote:
Netocrat <ne******@dodo.com.au> wrote:
On Sat, 16 Jul 2005 17:18:54 +0000, S.Tobias wrote: How could evaluating "*" - in the case where "&*" is not a no-op - not
result in taking a value?
Evaluating "*" and taking a value are two different processes.
1. The result of "*" is an lvalue (or function designator) (6.5.3.2#4).
2. If a (non-array) lvalue is not an operand to "&", "++", "--", "." or
"=", it is "converted to the value stored in the designated object
(and is no longer an lvalue)" (6.3.2.1#2) (that's when the value
is read).> Evaluating "*" and taking a value are two different
processes.


OK, there's a distinction, but the only case I can see it manifest is with
structures as this snippet shows:

int r;
int k[10];
struct {int i; int *j;} s, *sp = &s;
k[3] = 20;
s.j = k;
r = (*sp).j[3];

Considering the final expression in the context of *sp, obviously
6.3.2.1#2 applies and we get back an lvalue. But as you correctly reason,
according to 6.5.3.2#4 it is not immediately converted to the value of
*sp, but rather the "." operator is applied to obtain (*sp).j which is an
lvalue that immediate decays to a non-lvalue pointer and is indexed etc,
yielding a final lvalue which by 6.5.3.2#4 is converted to a value.


Correct.
So it's true that we do not fully "take the value" of (*sp), but we do
evaluate enough of it to find (*sp).j. At the least this requires
that we determine the address in sp and add the offset of j to it, and
access the contents referenced by j. So... that's quite a bit of "value
taking" ...
Yes. The Standard specifies that that member is read, and only that.
The implementation can read the struct as a whole, or its members
separately if it feels right, provided it doesn't make any visible
difference to the programmer, but this is not specified by the Std
(IOW what is specified is the minimum that must be done to execute
that fragment of a program).
An lvalue is an object locator, so to dereference sp into an lvalue you
have to hunt around and find the object that it references, which you
will then do something with. 6.3.2.1#2 describes what that something
might be, and in all cases it requires at least some part of the value
of *sp to be taken.

I'm not sure that there's ever a situation where we "evaluate *" without
"taking its value" in at least some way. Perhaps you can think of one
though. The whole point of expressing an lvalue in code (apart from with
sizeof) is to store into it or read from its storage in some way...
so why _would_ there be a situation where we don't take it's value?
[snip] I understand that it says that, I just don't understand *why*. I
haven't yet seen a satisfactory example where an lvalue that is of
incomplete struct type actually occurs in any context other than &*ps,
where we've established that it doesn't actually occur since the &* is
optimised away! And if it can occur, then what type of data does it store???

I see your problem is: why should incomplete type expression to be
an lvalue at all? The answer is: I don't know. The Standard
establishes a language (metalanguage) through which it describes
the C language. If it defines lvalue to be what it defines, you
have to follow it blindly. I myself don't agree with it, I hate it,
I have my own, better opinion on what an lvalue should be.
But in order to interpret correctly other parts of the Standard
you have to accept what it defines.
For example,
extern struct s s;
struct s *sp = &s;
void *vp = &s;
*sp; //UB
*vp; //okay
The first expression yields UB, and the second doesn't. The only reason
for that is that the fist is an lvalue, while the second is not.

The Standard could define C in a different way, specifying things
case by case. Then you would probably write today "why does the Std do
it like that, it's so hard to remember all these cases; there's this
nice idea of lvalue, why not generalize things?". Perhaps someone
tried to generalize, but it wasn't so easy. Perhaps there is
a third way.

And have always in mind that people write standards, and those same
people make errors. It's difficult to discuss things with the lack of
proper definitions. As you know by now, the Std defines as lvalues
expressions that should not be lvalues. IMO that's not the biggest
sin yet. Really bad thing is that the Std contradicts itself, because
some expressions that fulfill the definition of lvalue are explicitly
said not to be lvalues.
It is UB
if an lvalue doesn't designate an object, and it would be UB if "*"
were evaluated in this case;


It's not quite true perhaps; UB is invoked when an lvalue that doesn't
designate an object is evaluated. It seems that by not evaluating "*"
the Standard wants to accomodate invalid pointers (cf. result of "*").


I'm not sure of your point. I see nothing wrong with your original words.
My best interpretation is that you're saying that the &* no-op was added
to prevent conceptual NULL pointer dereferences, which I agree with.


Yes, and pointers to (and lvalues designating) one past the last array element
(it's automatically UB if they are operands to "*").
So again I'll point out C89 draft 3.3.3.2 which says that the operand of &
must be an object, and which the DRs clarify takes precedence. It doesn't
matter whether or not it is evaluated - it is required to designate an
object.
Right.
You argued previously that it is possible that ps points to a struct fully
defined externally. (I needed an incomplete struct pointer that points to a valid object, and
it was impossible to have both complete and incomplete struct type on one line
(well, it is possible, but not as nice).)In that case, and that case only, &*ps is not a
constraint violation under C90. So theoretically, this is fully compliant
code:
I think so, too.
/** Begin exts1.c **/
struct exts {int i; int j;} es, *esp = &es;
void x(void);
int main(void)
{
x();
}
/** End exts1.c **/

/** Begin exts2.c **/
struct exts *esp; ITYM: extern struct exts *esp; void x(void)
{
struct exts *stmp;
stmp = &*esp;
}
/** End exts2.c **/

Whereas if we remove the definition of esp from exts1.c, technically this ITYM remove the initialization of esp to &es is undefined behaviour under C90.
Yes.
In fact gcc gives an error in both cases in both C90 and C99 modes (but
we can assume that it is not properly implementing C99 here).


como did it fine.

One last remark: UB is not a disaster, it's just lack of a definition.
In this case I think it means C90 was defective, and C99 made a change
for better. I seriously doubt any compiler would produce extra code
in `x()' just waiting when `esp' doesn't point to an object to let
the daemons fly in the face of an unsuspecting programmer.
--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 15 '05 #153
On Wed, 20 Jul 2005 00:26:47 +0000, S.Tobias wrote:

<snip>
I see your problem is: why should incomplete type expression to be an
lvalue at all?
Yes, exactly. There's a need in the case of incomplete array and
partially complete struct expressions, but not but for totally
incomplete struct types.
The answer is: I don't know.
Perhaps comp.std.c would have an answer, but since it's only a minor
redundancy it's so not much of a problem.

<snip>
For example,
extern struct s s;
struct s *sp = &s;
void *vp = &s;
*sp; //UB
*vp; //okay
The first expression yields UB,
But you seemed to agree (as per the ext1/2.c example below) that this
is only the case if s is not fully defined externally.
and the second doesn't. The only reason for that is that the fist is an
lvalue, while the second is not.
Yes, 6.5.3.2 fails to define the behaviour. vp is a pointer type as
paragraph 2 requires, but no case in paragraph 4 applies, so *vp is
undefined by ommission.

<snip>
Really bad thing is that the Std contradicts itself, because some
expressions that fulfill the definition of lvalue are explicitly said
not to be lvalues.


Right - the decayed array type and the footnotes on casts,
conditionals, and commas.

<snip>
You argued previously that it is possible that ps points to a struct
fully defined externally.

(I needed an incomplete struct pointer that points to a valid object,
and it was impossible to have both complete and incomplete struct type
on one line (well, it is possible, but not as nice).)
In that case, and that case only, &*ps is not a
constraint violation under C90. So theoretically, this is fully
compliant code:


I think so, too.
/** Begin exts1.c **/
struct exts {int i; int j;} es, *esp = &es; void x(void); int
main(void)
{
x();
}
/** End exts1.c **/

/** Begin exts2.c **/
struct exts *esp;

ITYM: extern struct exts *esp;


I did, but in this situation extern is redundant, by 6.2.2#5.
void x(void)
{
struct exts *stmp;
stmp = &*esp;
}
/** End exts2.c **/

Whereas if we remove the definition of esp from exts1.c, technically
this

ITYM remove the initialization of esp to &es


I didn't, but that's an even better example.
is undefined behaviour under C90.


Yes.
In fact gcc gives an error in both cases in both C90 and C99 modes (but
we can assume that it is not properly implementing C99 here).


como did it fine.


I can't see a way to compile two separate files on como online so I
can't confirm that. Anyhow it's a difference that can't be detected at
compile time.

Nov 15 '05 #154
Netocrat wrote:
On Wed, 20 Jul 2005 00:26:47 +0000, S.Tobias wrote:

/** Begin exts1.c **/
struct exts {int i; int j;} es, *esp = &es; void x(void); int
main(void)
{
x();
}
/** End exts1.c **/

/** Begin exts2.c **/
struct exts *esp;

ITYM: extern struct exts *esp;


I did, but in this situation extern is redundant, by 6.2.2#5.


After reading Me's post in the current thread "extern" I see that
6.9.2#2 applies, and extern is not redundant after all. Excluding it
invokes UB.
void x(void)
{
struct exts *stmp;
stmp = &*esp;
}
/** End exts2.c **/


<snip rest>

Nov 15 '05 #155
Netocrat <ne******@dodo.com.au> wrote:
On Wed, 20 Jul 2005 00:26:47 +0000, S.Tobias wrote:

For example,
extern struct s s;
struct s *sp = &s;
void *vp = &s;
*sp; //UB
*vp; //okay
The first expression yields UB, and the second doesn't. The only reason for that is that the fist is an
lvalue, while the second is not.


Yes, 6.5.3.2 fails to define the behaviour. vp is a pointer type as
paragraph 2 requires, but no case in paragraph 4 applies, so *vp is
undefined by ommission.


I think you got it wrong this time. `*sp' is explicitly undefined
by 6.3.2.1#2, because it is an incomplete lvalue, and thus cannot be
converted to a value.

`*vp' is not an lvalue[*], and therefore it doesn't undergo
lvalue-to-value conversion, and it's behaviour is perfectly defined:
it is an expression statement, which is evalueated for its side
effects, and its (nonexistent) value is discarded.

`*vp' is as much valid an expression as a void function call is:
void f(), *pv = &some_object;
f(); //okay
*pv; //okay

[*] Well, actually 6.5.3.2#4 says it is an lvalue, but I think
the Standard is again wrong; I think it deserves a DR, but first
I'll check that this isn't already known.

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 15 '05 #156
On Wed, 20 Jul 2005 12:28:08 +0000, S.Tobias wrote:
Netocrat <ne******@dodo.com.au> wrote:
On Wed, 20 Jul 2005 00:26:47 +0000, S.Tobias wrote:
For example,
extern struct s s;
struct s *sp = &s;
void *vp = &s;
*sp; //UB
*vp; //okay
The first expression yields UB, and the second doesn't. The only reason for that is that the fist is an
lvalue, while the second is not.


Yes, 6.5.3.2 fails to define the behaviour. vp is a pointer type as
paragraph 2 requires, but no case in paragraph 4 applies, so *vp is
undefined by ommission.


I think you got it wrong this time. `*sp' is explicitly undefined
by 6.3.2.1#2, because it is an incomplete lvalue, and thus cannot be
converted to a value.


Yes of course, you are right.
`*vp' is not an lvalue[*], and therefore it doesn't undergo
lvalue-to-value conversion, and it's behaviour is perfectly defined:
it is an expression statement, which is evalueated for its side
effects, and its (nonexistent) value is discarded.
Perhaps you are right. I find the standard a little ambiguous here.
The first two sentences of 6.5.3.2#4 don't apply since by 6.2.5, void
is not an object, it's an incomplete type. That leaves things somewhat
undefined; the third sentence defines the resulting type, but is that
enough definition?

<snip>
[*] Well, actually 6.5.3.2#4 says it is an lvalue, but I think
the Standard is again wrong; I think it deserves a DR, but first
I'll check that this isn't already known.


6.5.3.2#4 only defines the result as an lvalue "if [the operand] points
to an object". By 6.2.5 void types are never objects.

Nov 15 '05 #157
Netocrat <ne******@dodo.com.au> wrote:
On Wed, 20 Jul 2005 12:28:08 +0000, S.Tobias wrote:
`*vp' is not an lvalue[*], and therefore it doesn't undergo
lvalue-to-value conversion, and it's behaviour is perfectly defined:
it is an expression statement, which is evalueated for its side
effects, and its (nonexistent) value is discarded.


Perhaps you are right. I find the standard a little ambiguous here.
The first two sentences of 6.5.3.2#4 don't apply since by 6.2.5, void
is not an object, it's an incomplete type.


[snip]
6.5.3.2#4 only defines the result as an lvalue "if [the operand] points
to an object". By 6.2.5 void types are never objects.


You still confuse lvalues with objects. Lvalue is an expression
(it's those characters - or rather tokens - that you type into your
editor: "*" and "vp" together). Object is an untyped range of bytes
in the run-time, nothing more. Type of an object is the type of
the lvalue that it is accessed with. (There's also an idea of "effective
type", but I don't want to go into details here.)

Lvalue is not an object. Lvalue designates an object (points to an
object, as if with a finger), and it is UB if there's no object.

All of these pointers point to the (same) object:
void *pv = malloc(10); assert(pv);
int *pi = pv;
struct s *ps = pv;
And lvalues designating that object are:
*pv;
*pi; //UB if sizeof(int) > 10
*ps; //UB (because of incomplete type)

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 15 '05 #158
S.Tobias wrote:
Netocrat <ne******@dodo.com.au> wrote:
On Wed, 20 Jul 2005 12:28:08 +0000, S.Tobias wrote:

`*vp' is not an lvalue[*], and therefore it doesn't undergo
lvalue-to-value conversion, and it's behaviour is perfectly defined:
it is an expression statement, which is evalueated for its side
effects, and its (nonexistent) value is discarded.


Perhaps you are right. I find the standard a little ambiguous here.
The first two sentences of 6.5.3.2#4 don't apply since by 6.2.5, void
is not an object, it's an incomplete type.


[snip]
6.5.3.2#4 only defines the result as an lvalue "if [the operand] points
to an object". By 6.2.5 void types are never objects.


You still confuse lvalues with objects.


Not true. I've been through enough back-and-forth in this thread and
others to at least have _that_ straight.

My argument was actually that since the void type is empty, a void
pointer could be considered as pointing to nothing, no matter what its
value. That is, a void pointer can never actually point to an object.

Nov 15 '05 #159
Netocrat <ne******@dodo.com.au> wrote:
S.Tobias wrote:
Netocrat <ne******@dodo.com.au> wrote: You still confuse lvalues with objects.
Not true.

[snip]

Okay. :-| Then there must be something else wrong with you:
That is, a void pointer can never actually point to an object.


Why do you keep writing things like this? Void pointer *can*
point to *any* object, that's its main purpose. It's that
the object's value cannot be accessed through void type,
the pointer has to be converted to other type (a different
pointer), but the whole expression is still based on the original
void pointer that points to that object, eg:
*(int*)vp;

If a void pointer doesn't point to an object, then where does
it point to?

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 15 '05 #160
S.Tobias wrote:
Netocrat <ne******@dodo.com.au> wrote:
S.Tobias wrote:
Netocrat <ne******@dodo.com.au> wrote: You still confuse lvalues with objects.
Not true.

[snip]

Okay. :-| Then there must be something else wrong with you:


I wonder what it could be? I understand your arguments, and I don't
require you to agree with mine, but if you give them more
consideration, you will possibly find that they're at least reasonable.
That is, a void pointer can never actually point to an object.


Why do you keep writing things like this?


Because the void type is unique. It is the only type that is both
empty, incomplete and can never be completed. In that sense how can we
consider a void pointer as pointing to "an object"? - it is clear that
void is the only type that can never represent an object, so a void
pointer can never point to an object. It may, however, be validly
converted to a pointer type that does.
Void pointer *can*
point to *any* object, that's its main purpose.
Informally I would also use a statement like that. But I don't think
it's strictly true (and the standard's wording convinces me that it's
not).

We rely on 6.3.2.3#1 to be able to convert without information loss
from a non-void pointer to a void pointer and back again, but they are
different pointer types, and nothing in the standard says that when the
information is stored in a void pointer, that we must consider the
conceptual thing that is the "void pointer" to be "pointing to an
object"; the definition of the void type actually makes that wrong in
the strict sense (I agree that informally we might use such wording).
It's that
the object's value cannot be accessed through void type,
No value at all (==void,empty) can be accessed through the void type,
let alone an object.
the pointer has to be converted to other type (a different
pointer), but the whole expression is still based on the original
void pointer that points to that object, eg:
*(int*)vp;

If a void pointer doesn't point to an object, then where does
it point to?
How would you instead answer "what does it point to?"

I don't see a strictly correct answer to your question (informally I
would say that it points to the original object as you have been
claiming). I'd describe a void pointer rather as holding pointing
information in a form that can be transferred back to an object pointer
without loss of meaning. But I wouldn't describe it as an object
pointer itself.

Now regarding whether dereferencing a void pointer is defined
behaviour, I said:
I find the standard a little ambiguous here.
The first two sentences of 6.5.3.2#4 don't apply since by 6.2.5, void
is not an object, it's an incomplete type.
Can you see where that statement is coming from now? 6.5.3.2#4 says
that "if [the operand] points to an object, the result is an lvalue
designating the object", but since a void pointer by definition does
not point to an object, this statement doesn't apply to a void pointer.
That leaves things somewhat
undefined; the third sentence defines the resulting type, but is that
enough definition?
So all that's defined is that the result has void type. OK, given that
there is no such thing as a void object anyway, I'll answer my
question: yes, that's enough definition. So I'm satisfied that at
least this part of the standard defines and allows for the
dereferencing of a void pointer.

Now you wrote:
[*] Well, actually 6.5.3.2#4 says it is an lvalue, but I think
the Standard is again wrong; I think it deserves a DR, but first
I'll check that this isn't already known.


You have misinterpreted 6.5.3.2#4. The result is only an lvalue if the
operand points to an object, which strictly speaking a void pointer
doesn't.

The paragraph says: "if it points to an object, the result is an lvalue
designating the object". Your argument implies that the object type
that the lvalue locates can be different to the type of expression
representing it (in this case, void), which is plainly untrue.

Don't get me wrong - I know that it's sometimes legal to access objects
through an lvalue of type other than the object's originally designated
type (in particular I'm a thinking of a character type), but in those
cases conceptually the lvalue _is_ accessing an object of the same type
as itself (eg. a char can be considered as a special object within a
bigger object of different type), whereas in the case of void it is not
(void is not an object like char is; it is empty and incompletable, so
an lvalue represented by a void expression cannot validly locate any
"object" within a different object).

Nov 15 '05 #161
Netocrat wrote:

S.Tobias wrote:

If a void pointer doesn't point to an object, then where does
it point to?


How would you instead answer "what does it point to?"


Allocated memory.

N869
7.20.3.3 The malloc function
Synopsis
[#1]
#include <stdlib.h>
void *malloc(size_t size);
Description
[#2] The malloc function allocates space for an object whose
size is specified by size and whose value is indeterminate.
Returns
[#3] The malloc function returns either a null pointer or a
pointer to the allocated space.

--
pete
Nov 15 '05 #162
pete wrote:
Netocrat wrote:
S.Tobias wrote:

If a void pointer doesn't point to an object, then where does
it point to?


How would you instead answer "what does it point to?"


Allocated memory.


Spot on and concise as usual.

The distinction between allocated memory and an object is that an
object has a type - its definition requires it to be capable of
representing values.

So Stan perhaps you would be willing to consider that a void pointer is
best defined as pointing to allocated memory and not an object.

Nov 15 '05 #163
Netocrat wrote:

pete wrote:
Netocrat wrote:
S.Tobias wrote:

> If a void pointer doesn't point to an object, then where does
> it point to?

How would you instead answer "what does it point to?"


Allocated memory.


Spot on and concise as usual.

The distinction between allocated memory and an object is that an
object has a type - its definition requires it to be capable of
representing values.


Maybe not.

N869
7.20.3 Memory management functions

Each such allocation shall yield a pointer to
an object disjoint from any other object.

--
pete
Nov 15 '05 #164
[I have been meaning to reply to this for quite a while now.]
On 11 Jul 2005 17:35:54 GMT, Chris Torek
<no****@torek.net> wrote:
[Given "int arr[N];" and considering "&arr" vs "&arr[0]")

I think the real question boils down to whether &arr and &arr[0]
will compare equal under *all* "well-defined" conversions -- which
may even be only those to "char *" and "void *" -- and then I think
the answer is "yes", so that we can in fact say that the converted
values are always identical as long as we do a sensible conversion.

In article <sl******************@ccserver.keris.net>
Chris Croughton <ch***@keristor.net> wrote:Is that actually defined by the standard?
At least implicitly, yes (I think). I have tried to argue the
opposite and always seem to run into a contradiction somewhere.
This is not entirely a satisfactory proof. :-)
I remember that in some pre-standard C compilers arrays were
actually implemented as pointers, so int arr[5]; would actually
expand to the equivalent in pseudo-assember:

arr: dw &_arr
_arr: dw ?[5]

(The array pointer itself might be declared in a read-only segment.)
This was true in BCPL and B, and even in NB, but not in C. See
<http://cm.bell-labs.com/cm/cs/who/dmr/chist.html> (the section
titled "Embryonic C"). Indeed, the elimination of the pointer
seems to have been the point at which the language's name changed
from "New B" to "C".
Is this sort of expansion actually banned by the standard ...


Yes. See Dennis' example with a struct that contains an array.
Where will you put the pointer?
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 15 '05 #165
On Sat, 23 Jul 2005 09:31:41 +0000, pete wrote:
Netocrat wrote:

pete wrote:
> Netocrat wrote:
> > S.Tobias wrote:
>
> > > If a void pointer doesn't point to an object, then where does it
> > > point to?
> >
> > How would you instead answer "what does it point to?"
>
> Allocated memory.


Spot on and concise as usual.

The distinction between allocated memory and an object is that an
object has a type - its definition requires it to be capable of
representing values.


Maybe not.

N869
7.20.3 Memory management functions

Each such allocation shall yield a pointer to an object disjoint
from any other object.


I hadn't looked at library functions. So what I described as "informal
wording" is actually used in the standard.

Stan said in a higher up post, "Object is an untyped range of bytes in the
run-time, nothing more. Type of an object is the type of the lvalue that
it is accessed with."

My idea of an object includes type (probably influenced by OO), but it
seems that Stan is correct and that C99 only requires that it "may" be
considered typed.

I don't think it's quite that clear-cut in C in general (the C89 draft
definition of an object, for example, doesn't use the word "type" at all
so there is no "may" qualification, but it specifically mentions
bit-fields, suggesting that type is an implicit property of an object).

So I will accept Stan's argument that by 6.5.3.2#4 dereferencing a void
pointer yields an lvalue which contradicts 6.3.2.1#1.

This problem would be solved if an object were necessarily typed and we
defined a void pointer as pointing to untyped storage, not an object, but
that's off-topic.

Nov 15 '05 #166
Netocrat wrote:
On Sat, 23 Jul 2005 09:31:41 +0000, pete wrote:

Netocrat wrote:
pete wrote:

Netocrat wrote:

>S.Tobias wrote:

>>If a void pointer doesn't point to an object, then where does it
>>point to?
>
>How would you instead answer "what does it point to?"

Allocated memory.

Spot on and concise as usual.

The distinction between allocated memory and an object is that an
object has a type - its definition requires it to be capable of
representing values.


Maybe not.

N869
7.20.3 Memory management functions

Each such allocation shall yield a pointer to an object disjoint
from any other object.

I hadn't looked at library functions. So what I described as "informal
wording" is actually used in the standard.

Stan said in a higher up post, "Object is an untyped range of bytes in the
run-time, nothing more. Type of an object is the type of the lvalue that
it is accessed with."

My idea of an object includes type (probably influenced by OO), but it
seems that Stan is correct and that C99 only requires that it "may" be
considered typed.

I don't think it's quite that clear-cut in C in general (the C89 draft
definition of an object, for example, doesn't use the word "type" at all
so there is no "may" qualification, but it specifically mentions
bit-fields, suggesting that type is an implicit property of an object).

So I will accept Stan's argument that by 6.5.3.2#4 dereferencing a void
pointer yields an lvalue which contradicts 6.3.2.1#1.

This problem would be solved if an object were necessarily typed and we
defined a void pointer as pointing to untyped storage, not an object, but
that's off-topic.

You seem to insist of making simple things complicated. An object is
simply a region of one or more bytes of storage. It doesn't require a
type to be an object. Consider..

typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned short ushort;

typedef struct {
uchar version; /* 00 0x03 or 0x83 (with .dbt file) */
uchar date[3]; /* 01 Date YY MM DD in binary */
ulong numrecs; /* 04 Number of records in data file */
ushort hdrlen; /* 08 Offset to first record */
ushort reclen; /* 0A Length of each record */
uchar reserved[20];/* 0C Balance of 32 bytes */
} HEADER;

HEADER *head;
void *vp;
vp = malloc(sizeof *head);

Assuming success, malloc returns an address of type (void*) which points
to 32 bytes of storage. This address is assigned to vp. Now vp points to
an object of unspecified type of 32 bytes. No part of the object can be
accessed through vp.

head = vp;

Now head points to the same object as vp. But head has a complete type
(namely HEADER*) and so the object can be accessed as *head and any of
its members as (*head).hdrlen or head->hdrlen.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 15 '05 #167
Netocrat <ne******@dodo.com.au> writes:
On Mon, 18 Jul 2005 00:10:22 -0700, Tim Rentsch wrote:
Netocrat <ne******@dodo.com.au> writes:
On Sun, 17 Jul 2005 12:09:39 -0700, Tim Rentsch wrote:

<snip>
The problem is that, as written, the standard says almost all
expressions are lvalues. I neglected when giving the original
quote to write:

6.3.2.1

1 An <i>lvalue</i> is an expression with an object type or an
incomplete type other than void; ...

The italics makes this statement the (only) definition, per
section 3, paragraph 1.


I can't argue against that. The draft document I use is plain-text
without italics.
The C standard document is one that should be interpreted
according to a literal reading; anything less means the authors
aren't doing their job.


I have accessed a later draft dated May 6 2005 with the same wording.
Can anyone comment on whether any committee members view the definition
as flawed?


When I raised this issue on comp.std.c some time ago, Doug Gwyn, who
is a committee member, seemed to think that my concerns were
incorrect. He did say at one point that the standard's definition of
lvalue needed more work, but not for the reasons I had been arguing;
he never explained what he meant.

The fundamental point of disagreement, I think, was about what a
"definition" should be. My position is that the definition of a
"foo", for example, should be sufficient to determine what is a foo
and what is not a foo. The definition can depend on terms defined
elsewhere, but once those terms are understood the definition itself
should be complete and unambiguous. Otherwise, though it may be a
useful statement about foos, it isn't a definition, and should not be
presented as one. This is especially important for invented terms
that are not expected to be understood

The C99 standard's so-called "definition" of the term "lvalue" is a
useful statement about lvalues, but since it does not allow the reader
to determine whether a given expression is an lvalue or not, I don't
consider it to be a valid definition.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #168
On Sat, 23 Jul 2005 19:18:30 -0400, Joe Wright wrote:
Netocrat wrote:
[conceding that the standard defines an object as storage not necessarily
typed, and that wording that I initially called informal is actually used
by the standard (ie that a void pointer points to an object)]
So I will accept Stan's argument that by 6.5.3.2#4 dereferencing a void
pointer yields an lvalue which contradicts 6.3.2.1#1.

This problem would be solved if an object were necessarily typed and we
defined a void pointer as pointing to untyped storage, not an object,
but that's off-topic.

You seem to insist of making simple things complicated.


Right, the current understanding that a void pointer points to potentially
untyped storage is better and more correct than considering its
destination as necessarily untyped.

But I do think that an object is best defined as typed.

Referring to object as not-necessarily-typed storage, the standard says:

6.5#6
If a value is stored into an object having no declared type through an
lvalue having a type that is not a character type, then the type of
the lvalue becomes the effective type of the object for that access
and for subsequent accesses that do not modify the stored value.

So using the standard:
untyped storage: a storage area returned by a memory allocation routine
and not yet assigned to.

In all other cases type has either been declared or determined by being
assigned to.

Untyped storage is the exception rather than the rule, and to me the term
object always connotes a type. So to me it is simpler to remove the
exceptional and unintuitive circumstance from the definition of object and
deal with it separately.

We could define:
an object: a typed data storage area
allocated storage: any defined or allocated data storage area including
untyped storage (as defined above)

Allocated storage would correspond to the current object definition.

All pointers must then point to allocated storage, which may or may not be
an object, and even if it is an object may not be the correct type. This
definition change would be reflected in the wording of 6.5.3.2#4, although
it wouldn't correct the current problem that dereferencing a void pointer
results in an lvalue.

I'm starting to get off-topic for clc though.
An object is
simply a region of one or more bytes of storage. It doesn't require a
type to be an object. Consider..


<snip>

Given that I'd already conceded that C99 defines an object that way, your
example didn't really add anything.

Nov 15 '05 #169
Keith Thompson wrote:
The fundamental point of disagreement, I think, was about what a
"definition" should be.


Do you have IS0 1087 ?


ISOllEC 2382-l : 1993

Other terms such as vocabulary, concept, term and definition,
are used in this part of ISO/IEC 2382
with the meaning defined in IS0 1087.
--
pete
Nov 15 '05 #170
pete <pf*****@mindspring.com> writes:
Keith Thompson wrote:
The fundamental point of disagreement, I think, was about what a
"definition" should be.


Do you have IS0 1087 ?


ISOllEC 2382-l : 1993

Other terms such as vocabulary, concept, term and definition,
are used in this part of ISO/IEC 2382
with the meaning defined in IS0 1087.


No, do you? Can someone summarize its definition of "definition"?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #171
Keith Thompson wrote:
pete <pf*****@mindspring.com> writes:
Keith Thompson wrote:
The fundamental point of disagreement, I think, was about what a
"definition" should be.


Do you have IS0 1087 ?


ISOllEC 2382-l : 1993

Other terms such as vocabulary, concept, term and definition,
are used in this part of ISO/IEC 2382
with the meaning defined in IS0 1087.


No, do you? Can someone summarize its definition of "definition"?


Definition:

ISO 1087:1990:
Statement which describes a concept and permits its differentiation
from other concepts within a system of concepts.

ISO 1087-1:2000:
Representation of a concept by a descriptive statement which serves to
differentiate it from related concepts.

Robert Gamble

Nov 15 '05 #172
Keith Thompson wrote:
When I raised this issue on comp.std.c some time ago, Doug Gwyn, who
is a committee member, seemed to think that my concerns were
incorrect. He did say at one point that the standard's definition of
lvalue needed more work, but not for the reasons I had been arguing;
he never explained what he meant.

The fundamental point of disagreement, I think, was about what a
"definition" should be. My position is that the definition of a
"foo", for example, should be sufficient to determine what is a foo
and what is not a foo.


I remember that.

http://groups-beta.google.com/group/...fc45c00?hl=en&

--
pete
Nov 15 '05 #173
"Robert Gamble" <rg*******@gmail.com> writes:
Keith Thompson wrote:
pete <pf*****@mindspring.com> writes:
> Keith Thompson wrote:
>
>> The fundamental point of disagreement, I think, was about what a
>> "definition" should be.
>
> Do you have IS0 1087 ?
>
>
>
>
> ISOllEC 2382-l : 1993
>
> Other terms such as vocabulary, concept, term and definition,
> are used in this part of ISO/IEC 2382
> with the meaning defined in IS0 1087.


No, do you? Can someone summarize its definition of "definition"?


Definition:

ISO 1087:1990:
Statement which describes a concept and permits its differentiation
from other concepts within a system of concepts.

ISO 1087-1:2000:
Representation of a concept by a descriptive statement which serves to
differentiate it from related concepts.


So as far as ISO 1087 is concerned, a "definition" distinguishes the
defined term from other terms, but doesn't necessarily distinguish
things that meet the definition from things that don't.

Sigh.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #174
On 16 Jul 2005 17:18:54 GMT, "S.Tobias"
<si***@FamOuS.BedBuG.pAlS.INVALID> wrote:
<snip>
I don't think so. In C90 6.2.2.1 there's a paragraph which is equivalent
of 6.3.2.1#2 in C99 (in n869.txt) (they seem the same, but I haven't
checked). It means that at least the value of `*n' is not taken (because
it is operand to "&"). I don't see any cv in C90 except that `*n' is
not strictly an lvalue, which cannot (in general) be established at
compile time (due to poor definition of an lvalue).

They aren't the same; the difference is small but vital.

C90 says "An _lvalue_ is an expression (with an object type or
an incomplete type other than *void*) that designates an object."
plus the same footnote that is #46 in C99. The use of italics
means this is the definition of the term. Obviously for some
expressions like *ptr in some cases whether it designates an object
(and thus is an lvalue) can only be determined at runtime, making it
impossible to enforce constraints at compiletime as clearly intended.

C99 attempted to fix this by making the "designate an object" a
_separate_ requirement not part of the definition. Unfortunately, as
you and Netocrat have discussed at great length, IINM significantly
greater length than the scores if not hundreds of times this has been
discussed previously, the changed wording taken literally allows
essentially all expressions including pure (r)values that can
(trivially) and should be rejected at compiletime.

Since various types and forms of expressions are specified as yielding
an lvalue or a non-lvalue based only on compiletime information, the
intent is clear to any reader familiar with general computer and 3GL
principles or the history of C or both; there is no evidence that
anyone has actually misunderstood this intent not just for debating
purposes; and the Standard committee apparently has had enough work on
real issues to keep it too busy to fix this.

- David.Thompson1 at worldnet.att.net
Nov 15 '05 #175
On Mon, 18 Jul 2005 12:44:00 +1000, Netocrat <ne******@dodo.com.au>
wrote:
On Mon, 18 Jul 2005 02:21:44 +0000, Dave Thompson wrote:
On Mon, 11 Jul 2005 09:22:08 +1000, Netocrat <ne******@dodo.com.au>
wrote:
On Mon, 11 Jul 2005 00:53:27 +0400, Alexei A. Frounze wrote: <snip>
> Anyway, can you suggest a declaration of the function's argument that
> would simultaneously satisfy:
> - being a pointer to an array of a fixed number of elements, say, 5
> integers - this array is to be constant, in other words, its elements
> can't be altered by using the pointer

No. To the best of my understanding it is not possible according to the
standard.

Yes. Exactly as the OP did, use a pointer actually to the array as a
whole, not to its elements, which is what you normally use in C and
what (C) programmers normally mean by "pointer to the/an array".

<snip> Yup, that all works fine Dave but what Alexei actually wanted was more
specific and can't be done - at least no one who's responded to this
thread so far has found a way.

He wanted to pass a pointer to an array of a certain number of elements
(i.e. your first prototype is insufficient, but your second is sufficient)
into a function and be guaranteed that the contents of the array could not
be modified within the function. But he also wanted to be able to pass in
parameters of a type that were not const-qualified in any way eg.
int(*)[5], and have them automatically cast to the required type ie const
int (*)[5]. But this seems to be prohibited by C's automatic
const-conversion rules.


Sorry, I forgot that part and answered only what he and you said in
these particular posts. Yes, there is no way to silently add const
within an array. Unfortunately.
- David.Thompson1 at worldnet.att.net
Nov 15 '05 #176
Dave Thompson wrote:
On 16 Jul 2005 17:18:54 GMT, "S.Tobias"
<si***@FamOuS.BedBuG.pAlS.INVALID> wrote: <snip>
In C90 6.2.2.1 there's a paragraph which is equivalent
of 6.3.2.1#2 in C99 (in n869.txt)

<snip> They aren't the same; the difference is small but vital.
<snip explanation of lvalue definition differences between C90/C99>

Your explanation was excellent, but for the second time in this thread
you've misread the original article. Look at the specific paragraphs
referenced again...
Unfortunately, as
you and Netocrat have discussed at great length, IINM significantly
greater length than the scores if not hundreds of times this has been
discussed previously


Right, it's been a long and somewhat pedantic thread. With the aim
something useful be distilled from it, and hopefully it need not be
repeated, I've summarised what at the end of this thread I understand
the lvalue problem in the C99 standard to be here:

http://members.dodo.com.au/~netocrat/c/lvalue.html

If anyone has any comments, they are welcome to email me. Of course
they could also post a response here. My intention is to reduce
recurring discussion of the issue by providing a statement that can be
referred to. It would be good to know that the statement is commonly
agreed as accurate by regulars here.

Should sufficient people agree that the page is accurate, and that it's
appropriate to do so, I'll also post the reference on comp.std.c.

<snip rest>

Nov 15 '05 #177
> If a void pointer doesn't point to an object, then where does
it point to?


What is the sound of one hand clapping? :-)

I haven't been following the whole thread, but to my mind saying
"a void pointer doesn't point to an object" is a lot like saying
"a const object can't be modified". Well, you *can* modify a
const object (or try to), but you'll need a cast, to get rid of
the constness so that the compiler won't complain about it.
Similarly, you can take a void pointer and pretend it points to
an object, and here you don't always even need an explicit cast,
because the compiler will perform the conversion implicitly if
you, for example, assign the void pointer to a variable of object
pointer type.

The analogy is far from perfect, of course, because trying to
modify a const object is usually cheating (else you wouldn't have
declared it const in the first place). Taking a void pointer,
on the other hand, and "pretending" that it points to an actual
object, is usually not cheating, because usually we're not
pretending -- we *know* that, just beneath the void * veneer,
the pointer actually does point to a real object.

(I suspect everyone understands this just fine, and that the
debate is one of those how-many-angels-can-dance-on-the-head-
of-a-pin ones having to do with excruciatingly close readings of
the Standard, and if so, sorry for restating the merely obvious.)

Steve Summit
sc*@eskimo.com
Nov 15 '05 #178
Keith Thompson <ks***@mib.org> wrote:

So as far as ISO 1087 is concerned, a "definition" distinguishes the
defined term from other terms, but doesn't necessarily distinguish
things that meet the definition from things that don't.

Sigh.


So you don't like the definition of "definition"? :-)

-Larry Jones

Hmm... That might not be politic. -- Calvin
Nov 15 '05 #179
la************@ugs.com writes:
Keith Thompson <ks***@mib.org> wrote:

So as far as ISO 1087 is concerned, a "definition" distinguishes the
defined term from other terms, but doesn't necessarily distinguish
things that meet the definition from things that don't.

Sigh.


So you don't like the definition of "definition"? :-)


No, I don't. :-|

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #180
"Robert Gamble" <rg*******@gmail.com> writes:
Keith Thompson wrote:
pete <pf*****@mindspring.com> writes:
Keith Thompson wrote:

> The fundamental point of disagreement, I think, was about what a
> "definition" should be.

Do you have IS0 1087 ?


ISOllEC 2382-l : 1993

Other terms such as vocabulary, concept, term and definition,
are used in this part of ISO/IEC 2382
with the meaning defined in IS0 1087.


No, do you? Can someone summarize its definition of "definition"?


Definition:

ISO 1087:1990:
Statement which describes a concept and permits its differentiation
from other concepts within a system of concepts.

ISO 1087-1:2000:
Representation of a concept by a descriptive statement which serves to
differentiate it from related concepts.


To see that the definition for lvalue:

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

is bad, simply consider the question, "Does this statement allow
differentiation of this concept from other (related) concepts?"
Obviously it does not.
Nov 15 '05 #181
Keith Thompson wrote:
"Robert Gamble" <rg*******@gmail.com> writes:
Definition:

ISO 1087:1990:
Statement which describes a concept and permits its differentiation
from other concepts within a system of concepts.

ISO 1087-1:2000:
Representation of a concept by a descriptive statement which serves to
differentiate it from related concepts.


So as far as ISO 1087 is concerned, a "definition" distinguishes the
defined term from other terms, but doesn't necessarily distinguish
things that meet the definition from things that don't.


This reflects a different kind of definition -- the sort that you would
expect in a dictionary, versus the sort that you would expect in the C
standard.

Nobody expects the definitions in general-purpose dictionary to provide
an absolutely accurate treatise on what can be considered a "flower" and
what cannot, let alone more abstract concepts like "love". A reasonable
description of the concept, that allows you to tell it apart from other
similar concepts, is enough.

On the other hand, the C Standard is expected to be used to create a
family of computer programs, called "implementations", which can all
accept exactly the same input and (produce programs that) have exactly
the same behaviour. The Standard is expected to be the final arbiter of
whether an implementation is correct or incorrect. For this reason, any
definitions in the Standard should be held to a higher standard.

--
Simon Biber.
Nov 15 '05 #182
Simon Biber <ne**@ralmin.cc> wrote:

Nobody expects the definitions in general-purpose dictionary to provide
an absolutely accurate treatise on what can be considered a "flower" and
what cannot, let alone more abstract concepts like "love". A reasonable
description of the concept, that allows you to tell it apart from other
similar concepts, is enough.

On the other hand, the C Standard is expected to be used to create a
family of computer programs, called "implementations", which can all
accept exactly the same input and (produce programs that) have exactly
the same behaviour. The Standard is expected to be the final arbiter of
whether an implementation is correct or incorrect. For this reason, any
definitions in the Standard should be held to a higher standard.


I disagree. The *definitions* in the standard, like the definitions in
a dictionary, are just intended to be reasonable descriptions of the
concepts. The rest of the standard is the accurate treatise describing
them in detail.

-Larry Jones

In a minute, you and I are going to settle this out of doors. -- Calvin
Nov 15 '05 #183
la************@ugs.com writes:
Simon Biber <ne**@ralmin.cc> wrote:
Nobody expects the definitions in general-purpose dictionary to provide
an absolutely accurate treatise on what can be considered a "flower" and
what cannot, let alone more abstract concepts like "love". A reasonable
description of the concept, that allows you to tell it apart from other
similar concepts, is enough.

On the other hand, the C Standard is expected to be used to create a
family of computer programs, called "implementations", which can all
accept exactly the same input and (produce programs that) have exactly
the same behaviour. The Standard is expected to be the final arbiter of
whether an implementation is correct or incorrect. For this reason, any
definitions in the Standard should be held to a higher standard.


I disagree. The *definitions* in the standard, like the definitions in
a dictionary, are just intended to be reasonable descriptions of the
concepts. The rest of the standard is the accurate treatise describing
them in detail.


In my opinion, the C99 standard's definition of "lvalue" fails even by
that criterion. If I had never heard of an "lvalue", reading the
definition in C99 6.3.2.1p1 would not give me a good idea of what it's
supposed to be. The core of what an lvalue is all about is that it
(at least potentially) designates an object. The C90 definition
captured this idea; the C99 definition does not.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #184
In article <kf*************@alumnus.caltech.edu> Tim Rentsch <tx*@alumnus.caltech.edu> writes:
"Robert Gamble" <rg*******@gmail.com> writes: ....
Definition:

ISO 1087:1990:
Statement which describes a concept and permits its differentiation
from other concepts within a system of concepts.
Badly worded, I think.
ISO 1087-1:2000:
Representation of a concept by a descriptive statement which serves to
differentiate it from related concepts.


Idem.
To see that the definition for lvalue:
An lvalue is an expression with an object type
or an incomplete type other than void;
is bad, simply consider the question, "Does this statement allow
differentiation of this concept from other (related) concepts?"
Obviously it does not.


It does distinguish an lvalue from a non-lvalue. And that is one of
the reasons I think the 1087 definitions are bad. In general the
only related concept from which a definition distinguishes a particular
concept, is the negation of that particular concept. In mathematics
almost all definitions are like this. (An infinite set is blah-blah.
This only distinguishes the infinite sets from the non-infinite, or
finite, sets.)
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 15 '05 #185
"Dik T. Winter" <Di********@cwi.nl> writes:
In article <kf*************@alumnus.caltech.edu> Tim Rentsch <tx*@alumnus.caltech.edu> writes:
> "Robert Gamble" <rg*******@gmail.com> writes: ...
> > Definition:
> >
> > ISO 1087:1990:
> > Statement which describes a concept and permits its differentiation
> > from other concepts within a system of concepts.
Badly worded, I think.
> > ISO 1087-1:2000:
> > Representation of a concept by a descriptive statement which serves to
> > differentiate it from related concepts.


Idem.
> To see that the definition for lvalue:
> An lvalue is an expression with an object type
> or an incomplete type other than void;
> is bad, simply consider the question, "Does this statement allow
> differentiation of this concept from other (related) concepts?"
> Obviously it does not.


It does distinguish an lvalue from a non-lvalue.


It's hard to consider this response as serious. Obviously the given
definition serves to differentiate the concept of "lvalue" from the
concepts of kumquat, electromagnetic field, or prime numbers. Clearly
though the statements in ISO 1087 are meant to imply that a definition
should allow differentiation from all (distinct) related concepts, not
just from some of them.

And that is one of
the reasons I think the 1087 definitions are bad. In general the
only related concept from which a definition distinguishes a particular
concept, is the negation of that particular concept. In mathematics
almost all definitions are like this. (An infinite set is blah-blah.
This only distinguishes the infinite sets from the non-infinite, or
finite, sets.)


The definition of a group clearly distinguishes it from the concept of
a field. Are groups and fields related concepts? I think most
mathematicians would say yes. Probably more to the point, any set of
concepts discussed in a single ISO document are related concepts, if
for no other reason than that they all pertain to the topic the
document addresses.

I agree that the definition of the term "definition" is 1087 can and
should be improved. But the definition of "lvalue" fails even the
weak test provided by 1087. In particular, the definition of the term
"lvalue" does not allow <the concept of lvalue> to be differentiated
from <the concept of an expression with an object type or an incomplete
type other than void>. (It isn't necessary to give a concept a name
for the concept to exist.) Since these two concepts are *supposed*
to be distinct, the definition should allow them to be differentiated
rather than saying that they are the same.
Nov 15 '05 #186
In article <kf*************@alumnus.caltech.edu> Tim Rentsch <tx*@alumnus.caltech.edu> writes:
"Dik T. Winter" <Di********@cwi.nl> writes: ....
> To see that the definition for lvalue:
> An lvalue is an expression with an object type
> or an incomplete type other than void;
> is bad, simply consider the question, "Does this statement allow
> differentiation of this concept from other (related) concepts?"
> Obviously it does not.


It does distinguish an lvalue from a non-lvalue.


It's hard to consider this response as serious.


It *was* serious.
And that is one of
the reasons I think the 1087 definitions are bad. In general the
only related concept from which a definition distinguishes a particular
concept, is the negation of that particular concept. In mathematics
almost all definitions are like this. (An infinite set is blah-blah.
This only distinguishes the infinite sets from the non-infinite, or
finite, sets.)


The definition of a group clearly distinguishes it from the concept of
a field. Are groups and fields related concepts?


Yes, they are related. So much so that every field is also a group (a field
is an additive group with quite a bit more structure). So the definition of
a group should not clearly distinguish it from the concept of a field.
To get an analogue you might say that the definition of field (a field is
a commutative ring where each element has a multiplicative inverse),
distinguishes fields from rings that are not fields.
In particular, the definition of the term
"lvalue" does not allow <the concept of lvalue> to be differentiated
from <the concept of an expression with an object type or an incomplete
type other than void>. (It isn't necessary to give a concept a name
for the concept to exist.) Since these two concepts are *supposed*
to be distinct, the definition should allow them to be differentiated
rather than saying that they are the same.


Why do you think those two concepts are supposed to be different? I
would rather think (given the definition) that they are supposed to
be the same.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 15 '05 #187
"Dik T. Winter" <Di********@cwi.nl> writes:
In article <kf*************@alumnus.caltech.edu> Tim Rentsch
<tx*@alumnus.caltech.edu> writes:

[...]
> In particular, the definition of the term
> "lvalue" does not allow <the concept of lvalue> to be differentiated
> from <the concept of an expression with an object type or an incomplete
> type other than void>. (It isn't necessary to give a concept a name
> for the concept to exist.) Since these two concepts are *supposed*
> to be distinct, the definition should allow them to be differentiated
> rather than saying that they are the same.


Why do you think those two concepts are supposed to be different? I
would rather think (given the definition) that they are supposed to
be the same.


Given the definition, they are the same. That's the problem.

The integer constant 42 is <an expression with an object type or an
incomplete type other than void>. It is not intended to be an lvalue.
A good definition of lvalue would tell us that 42 is not an lvalue;
the current on doesn't.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #188
"Dik T. Winter" <Di********@cwi.nl> writes:
In article <kf*************@alumnus.caltech.edu>
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
> "Dik T. Winter" <Di********@cwi.nl> writes: ...
> > > To see that the definition for lvalue:
> > > An lvalue is an expression with an object type
> > > or an incomplete type other than void;
> > > is bad, simply consider the question, "Does this statement allow
> > > differentiation of this concept from other (related) concepts?"
> > > Obviously it does not.
> >
> > It does distinguish an lvalue from a non-lvalue.

>
> It's hard to consider this response as serious.


It *was* serious.


Yes, I see that. Maybe I should have said "I don't see what
point you're trying to make". Having seen no small number of
articles written by Dik Winter, and finding them much more often
than not to be relevant and offer some level of insight, I found
the comments in the lvalues/definitions posting rather baffling.
Anyway, no matter.

[snip]
> In particular, the definition of the term
> "lvalue" does not allow <the concept of lvalue> to be differentiated
> from <the concept of an expression with an object type or an incomplete
> type other than void>. (It isn't necessary to give a concept a name
> for the concept to exist.) Since these two concepts are *supposed*
> to be distinct, the definition should allow them to be differentiated
> rather than saying that they are the same.


Why do you think those two concepts are supposed to be different? I
would rather think (given the definition) that they are supposed to
be the same.


That's sort of where this subthread started. The definition of
lvalue (given in 6.3.2.1 p1) says that an lvalue is (defined to
be) an expression with an object type or an incomplete type
other than void; whereas, as many or most regular readers of
CLC know, an lvalue is *supposed* to be something else (roughly
speaking, an expression that forms an address, which address
needs to be implicitly dereferenced to get a value, or which in
certain cases may be used to store a value into an object at
that address).

Why do people (including myself) think this? Various statements
in sections 6.5.x that certain kinds of expressions -- but not
all expressions with object type -- are lvalues; and, footnotes
here and there that other kinds of expressions (still with
object type) are not lvalues. Other related comments also; for
example, in talking about the address-of operator, 6.5.3.2 says
the operand of '&' shall be (other unrelated stuff or) an
lvalue (that isn't a register or referring to a bit-field).
Clearly this restriction isn't meant to allow all expressions
of object type: the expression

&(a+b)

is nonsense.
Nov 15 '05 #189
Keith Thompson wrote:
"Dik T. Winter" <Di********@cwi.nl> writes:
In article <kf*************@alumnus.caltech.edu> Tim Rentsch
<tx*@alumnus.caltech.edu> writes:


[...]
> In particular, the definition of the term
> "lvalue" does not allow <the concept of lvalue> to be differentiated
> from <the concept of an expression with an object type or an incomplete
> type other than void>. (It isn't necessary to give a concept a name
> for the concept to exist.) Since these two concepts are *supposed*
> to be distinct, the definition should allow them to be differentiated
> rather than saying that they are the same.


Why do you think those two concepts are supposed to be different? I
would rather think (given the definition) that they are supposed to
be the same.

Given the definition, they are the same. That's the problem.

The integer constant 42 is <an expression with an object type or an
incomplete type other than void>. It is not intended to be an lvalue.
A good definition of lvalue would tell us that 42 is not an lvalue;
the current on doesn't.

I see 42 as an expression of a value with int type. given ..
int a;
a = 42;
... the expression a is the int typed object (an lvalue) and 42 is the
int typed value. It is absurd to suggest that a value with int type is
an object.

That 42 has int type does not say (to me) that it has object type.

The line forms over here..

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 15 '05 #190
Joe Wright <jo********@comcast.net> writes:
Keith Thompson wrote:
"Dik T. Winter" <Di********@cwi.nl> writes:
In article <kf*************@alumnus.caltech.edu> Tim Rentsch
<tx*@alumnus.caltech.edu> writes:

[...]
> In particular, the definition of the term
> "lvalue" does not allow <the concept of lvalue> to be differentiated
> from <the concept of an expression with an object type or an incomplete
> type other than void>. (It isn't necessary to give a concept a name
> for the concept to exist.) Since these two concepts are *supposed*
> to be distinct, the definition should allow them to be differentiated
> rather than saying that they are the same.

Why do you think those two concepts are supposed to be different? I
would rather think (given the definition) that they are supposed to
be the same.

Given the definition, they are the same. That's the problem.
The integer constant 42 is <an expression with an object type or an
incomplete type other than void>. It is not intended to be an lvalue.
A good definition of lvalue would tell us that 42 is not an lvalue;
the current on doesn't.

I see 42 as an expression of a value with int type. given ..
int a;
a = 42;
.. the expression a is the int typed object (an lvalue) and 42 is the
int typed value. It is absurd to suggest that a value with int type is
an object.

That 42 has int type does not say (to me) that it has object type.

The line forms over here..


A value with int type is not necessarily an object, but int is
definitely an object type. C99 6.2.5 says:

Types are partitioned into _object types_ (types that fully
describe objects), _function types_ (types that describe
functions), and _incomplete types_ (types that describe objects
but lack information needed to determine their sizes).

Since int is a type, and it's neither a function type nor an
incomplete type, it ust be an object type.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #191
Keith Thompson wrote:
Joe Wright <jo********@comcast.net> writes:
Keith Thompson wrote:
"Dik T. Winter" <Di********@cwi.nl> writes:
In article <kf*************@alumnus.caltech.edu> Tim Rentsch
<tx*@alumnus.caltech.edu> writes:

[...]
> In particular, the definition of the term
>"lvalue" does not allow <the concept of lvalue> to be differentiated
>from <the concept of an expression with an object type or an incomplete
>type other than void>. (It isn't necessary to give a concept a name
>for the concept to exist.) Since these two concepts are *supposed*
>to be distinct, the definition should allow them to be differentiated
>rather than saying that they are the same.

Why do you think those two concepts are supposed to be different? I
would rather think (given the definition) that they are supposed to
be the same.

Given the definition, they are the same. That's the problem.
The integer constant 42 is <an expression with an object type or an
incomplete type other than void>. It is not intended to be an lvalue.
A good definition of lvalue would tell us that 42 is not an lvalue;
the current on doesn't.


I see 42 as an expression of a value with int type. given ..
int a;
a = 42;
.. the expression a is the int typed object (an lvalue) and 42 is the
int typed value. It is absurd to suggest that a value with int type is
an object.

That 42 has int type does not say (to me) that it has object type.

The line forms over here..

A value with int type is not necessarily an object, but int is
definitely an object type. C99 6.2.5 says:

Types are partitioned into _object types_ (types that fully
describe objects), _function types_ (types that describe
functions), and _incomplete types_ (types that describe objects
but lack information needed to determine their sizes).

Since int is a type, and it's neither a function type nor an
incomplete type, it ust be an object type.

You clearly (tentatively?) agree with me. Thanks. But you say "A value
with int type is not necessarily an object..". I contend that a value is
never an object. Objects are so construed so as to contain values.

Much of our discourse here in c.l.c is to interpret the meaning of the
scribes of C99 with the inferrence that the scribes are somehow inspired
and therfore infallible. Utter nonsense to me.

It is the gospel according to DMR as described by BWK which sustains and
empowers me up to and including C89.

Who needs or even wants C99?

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 15 '05 #192
Joe Wright <jo********@comcast.net> writes:
Keith Thompson wrote:
Joe Wright <jo********@comcast.net> writes:
Keith Thompson wrote:

"Dik T. Winter" <Di********@cwi.nl> writes:
>In article <kf*************@alumnus.caltech.edu> Tim Rentsch
><tx*@alumnus.caltech.edu> writes:

[...]
>> In particular, the definition of the term
>>"lvalue" does not allow <the concept of lvalue> to be differentiated
>>from <the concept of an expression with an object type or an incomplete
>>type other than void>. (It isn't necessary to give a concept a name
>>for the concept to exist.) Since these two concepts are *supposed*
>>to be distinct, the definition should allow them to be differentiated
>>rather than saying that they are the same.
>
>Why do you think those two concepts are supposed to be different? I
>would rather think (given the definition) that they are supposed to
>be the same.

Given the definition, they are the same. That's the problem.
The integer constant 42 is <an expression with an object type or an
incomplete type other than void>. It is not intended to be an lvalue.
A good definition of lvalue would tell us that 42 is not an lvalue;
the current on doesn't.
I see 42 as an expression of a value with int type. given ..
int a;
a = 42;
.. the expression a is the int typed object (an lvalue) and 42 is the
int typed value. It is absurd to suggest that a value with int type is
an object.

That 42 has int type does not say (to me) that it has object type.

The line forms over here..

A value with int type is not necessarily an object, but int is
definitely an object type. C99 6.2.5 says:
Types are partitioned into _object types_ (types that fully
describe objects), _function types_ (types that describe
functions), and _incomplete types_ (types that describe objects
but lack information needed to determine their sizes).
Since int is a type, and it's neither a function type nor an
incomplete type, it ust be an object type.

You clearly (tentatively?) agree with me. Thanks. But you say "A value
with int type is not necessarily an object..". I contend that a value
is never an object. Objects are so construed so as to contain values.


Right, values and objects are two distinct things, and a value is
never an object. My "not necessarily" wasn't intended to exclude
that; I just didn't take the time to think it through, and the point
wasn't particularly relevant.

But I don't see how you conclude that I agree with you. You wrote
(see above):

That 42 has int type does not say (to me) that it has object type.

I unequivocally disagreed with that statement. The fact that 42 has
int type means that it *does* have object type.

Just what did you think I was agreeing with?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #193
In article <kf*************@alumnus.caltech.edu> Tim Rentsch <tx*@alumnus.caltech.edu> writes:
"Dik T. Winter" <Di********@cwi.nl> writes: ....
Why do you think those two concepts are supposed to be different? I
would rather think (given the definition) that they are supposed to
be the same.


That's sort of where this subthread started.


Yes, I see now what your problem is (at least, according to my draft standard).
Let's have a look at the definition:
> > > An lvalue is an expression with an object type
> > > or an incomplete type other than void;


That it does not distinguish from related concepts is irrelevant (in most
of mathematics and computer science a definition just gives a name to some
concept with, hopefully, means to determine whether something falls under
the definition or not).

But there is a sentence following it:
"if an lvalue does not designate an object when it is evaluated, the
behavior is undefined."
So, while the constant 42 is of an object type, it is not an object, and
any use as an lvalue will result in undefined behaviour.

Back to your comments: The definition of
lvalue (given in 6.3.2.1 p1) says that an lvalue is (defined to
be) an expression with an object type or an incomplete type
other than void; whereas, as many or most regular readers of
CLC know, an lvalue is *supposed* to be something else (roughly
speaking, an expression that forms an address, which address
needs to be implicitly dereferenced to get a value, or which in
certain cases may be used to store a value into an object at
that address).
I do not know whether this comment is indeed true. I am not going to
read the complete standard now. But *when* an lvalue that is not an
object type is evaluated, the result is UB. Which means that an
evaluatable lvalue is precisely what you describe. (I do not know
off-hand under what circumstances an lvalue is not evaluated.)
Why do people (including myself) think this? Various statements
in sections 6.5.x that certain kinds of expressions -- but not
all expressions with object type -- are lvalues;
Pray provide a reference. I have looked through the draft and did
not find any such statements.
and, footnotes
here and there that other kinds of expressions (still with
object type) are not lvalues.
Again, pray provide references.
Other related comments also; for
example, in talking about the address-of operator, 6.5.3.2 says
the operand of '&' shall be (other unrelated stuff or) an
lvalue (that isn't a register or referring to a bit-field).
Clearly this restriction isn't meant to allow all expressions
of object type: the expression
&(a+b)
is nonsense.


Depends on the types of a and b. But when they are (say) integer
variables, the expression is indeed an lvalue. But the address
operator requires evaluation, and there you are. UB, because there
is not an object.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 15 '05 #194
In article <ln************@nuthaus.mib.org> Keith Thompson <ks***@mib.org> writes:
....
The integer constant 42 is <an expression with an object type or an
incomplete type other than void>. It is not intended to be an lvalue.
Why do you think so?
A good definition of lvalue would tell us that 42 is not an lvalue;
the current on doesn't.


But it *is* an lvalue. However, any use of it *as* an lvalue will result
in undefined behaviour. So you may write:
&42
without problems (there is neither a syntactic error, nor a semantic error),
but that use is undefined behaviour. So it can do anything. There might
even be conforming implementations that, when giving the following programme:
#include <stdio.h>
int main(void) {
&42 = 5;
printf("%d\n", 42);
}
will happily give 5 as output.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 15 '05 #195
"Dik T. Winter" <Di********@cwi.nl> writes:
In article <kf*************@alumnus.caltech.edu> Tim Rentsch
<tx*@alumnus.caltech.edu> writes:
> "Dik T. Winter" <Di********@cwi.nl> writes: ...
> > Why do you think those two concepts are supposed to be different? I
> > would rather think (given the definition) that they are supposed to
> > be the same.

>
> That's sort of where this subthread started.


Yes, I see now what your problem is (at least, according to my draft
standard). Let's have a look at the definition:
> > > > > An lvalue is an expression with an object type
> > > > > or an incomplete type other than void;
That it does not distinguish from related concepts is irrelevant (in most
of mathematics and computer science a definition just gives a name to some
concept with, hopefully, means to determine whether something falls under
the definition or not).

But there is a sentence following it:
"if an lvalue does not designate an object when it is evaluated, the
behavior is undefined."
So, while the constant 42 is of an object type, it is not an object, and
any use as an lvalue will result in undefined behaviour.


You say "any use *as an lvalue*". The standard says the behavior is
undefined *when it is evaluated*; it doesn't say "as an lvalue".

An lvalue is a kind of expression (all lvalues are expressions; not all
expressions are lvalues). If 42 is an lvalue, then it is evaluated in

int x;
x = 42;

and a literal reading of the standard implies that this evaluation
invokes undefined behavior.

The intent is that 42 is not an lvalue (though it is an expression
with an object type), and that evaluating it does not invoke undefined
behavior.
Back to your comments:
> The definition of
> lvalue (given in 6.3.2.1 p1) says that an lvalue is (defined to
> be) an expression with an object type or an incomplete type
> other than void; whereas, as many or most regular readers of
> CLC know, an lvalue is *supposed* to be something else (roughly
> speaking, an expression that forms an address, which address
> needs to be implicitly dereferenced to get a value, or which in
> certain cases may be used to store a value into an object at
> that address).
I do not know whether this comment is indeed true. I am not going to
read the complete standard now. But *when* an lvalue that is not an
object type is evaluated, the result is UB.


Was this a typo?

An lvalue is always of an object type, both by definition and by
intent. UB is invoked when an lvalue that doesn't designate an object
is evaluated. (Being of an object type and designating an object are
two very different things.)
Which means that an
evaluatable lvalue is precisely what you describe. (I do not know
off-hand under what circumstances an lvalue is not evaluated.)


When it's the operand of sizeof (unless it designates a VLA). When
it's the right operand of an "&&" operator whose left operand is zero.
When it appears in a function that isn't called. And so forth.
> Why do people (including myself) think this? Various statements
> in sections 6.5.x that certain kinds of expressions -- but not
> all expressions with object type -- are lvalues;


Pray provide a reference. I have looked through the draft and did
not find any such statements.


For example, 6.5.16p3:

An assignment operator stores a value in the object designated by
the left operand. An assignment expression has the value of the
left operand after the assignment, but is not an lvalue.
> and, footnotes
> here and there that other kinds of expressions (still with
> object type) are not lvalues.


Again, pray provide references.


6.5.2.5, footnote 80, says the result of a cast expression is not
an lvalue.

6.5.4, footnote 85, says that a cast does not yield an lvalue.

Etc.
> Other related comments also; for
> example, in talking about the address-of operator, 6.5.3.2 says
> the operand of '&' shall be (other unrelated stuff or) an
> lvalue (that isn't a register or referring to a bit-field).
> Clearly this restriction isn't meant to allow all expressions
> of object type: the expression
> &(a+b)
> is nonsense.


Depends on the types of a and b. But when they are (say) integer
variables, the expression is indeed an lvalue. But the address
operator requires evaluation, and there you are. UB, because there
is not an object.


No, it's a constraint violation (and no, it doesn't depend on the
types of the operands).

6.5.3.2p1 says that the operand of the unary & operator shall be
"... or an lvalue that designates an object that is ...". (The stuff
I've left out refers to function designators, bit fields, register
variables, and so forth, none of which is relevant here.) Given the
*intended* meaning of "lvalue", a+b is not an lvalue, so &(a+b)
violates a constraint. It doesn't merely invoke undefined behavior.

The statement that evaluating an lvalue that doesn't designate an
object invokes UB was intended to cover things like this:

int *ptr = NULL;
int i = *ptr;

*ptr is an lvalue, but it doesn't designate an object when it's
evaluated, so the evaluation invokes undefined behavior.

&(a+b) is no more or less sensible than x+3=42 or 1=2 (those are C
assignments, not mathematical comparisons). All are constraint
violations.

The only real problem is that this isn't as clear as it should be
because the definition of "lvalue" is broken.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #196
"Dik T. Winter" <Di********@cwi.nl> writes:
In article <ln************@nuthaus.mib.org> Keith Thompson
<ks***@mib.org> writes:
...
> >> The integer constant 42 is <an expression with an object type or an
> >> incomplete type other than void>. It is not intended to be an lvalue.
Why do you think so?


See footnote 53 in C99 6.3.2.1:

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.

42 is not an "object locator value"; there is no object associated
with it.

The C90 standard's definition of lvalue is:

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

42 is obviously not an lvalue under this definition. But the C90
definition is flawed; it implies that the name of a pointer object is
an lvalue if and only if it designates an object, which can be
determined only at execution time. The C99 definition was intended to
keep the same intended meaning while resolving this flaw;
unfortunately, it dropped the idea of designating an object, which is
what an lvalue is all about.

The C99 Rationale, in section 6.3.2.1, says:

A difference of opinion within the C community centered around the
meaning of _lvalue_, one group considering an lvalue to be any
kind of object locator, another group holding that an lvalue is
meaningful on the left side of an assigning operator. The C89
Committee adopted the definition of lvalue as an object
locator. The term _modifiable lvalue_ is used for the second of
the above concepts.
> >> A good definition of lvalue would tell us that 42 is not an lvalue;
> >> the current on doesn't.


But it *is* an lvalue.

[...]

Only if you read the C99 standard's definition of "lvalue" literally.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #197
"Dik T. Winter" <Di********@cwi.nl> wrote:
In article <ln************@nuthaus.mib.org> Keith Thompson <ks***@mib.org> writes:
...
> >> A good definition of lvalue would tell us that 42 is not an lvalue;
> >> the current on doesn't.


But it *is* an lvalue. However, any use of it *as* an lvalue will result
in undefined behaviour.


Quite. Which is clearly the wrong thing. Currently, thanks to C99,
correct, but still Wrong.

Richard
Nov 15 '05 #198
"Dik T. Winter" <Di********@cwi.nl> writes:
In article <kf*************@alumnus.caltech.edu>
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
[snip]
> > > > > An lvalue is an expression with an object type
> > > > > or an incomplete type other than void;
[snip]
But there is a sentence following it:
"if an lvalue does not designate an object when it is evaluated, the
behavior is undefined."
So, while the constant 42 is of an object type, it is not an object, and
any use as an lvalue will result in undefined behaviour.
What I think you mean to say is: according to how lvalue is
defined in the standard, any evaluation of 42 (because it is
an lvalue and does not designate an object) will result in
undefined behavior.

Clearly an evaluation of an integer constant isn't supposed to
cause undefined behavior.

Back to your comments:
> The definition of
> lvalue (given in 6.3.2.1 p1) says that an lvalue is (defined to
> be) an expression with an object type or an incomplete type
> other than void; whereas, as many or most regular readers of
> CLC know, an lvalue is *supposed* to be something else (roughly
> speaking, an expression that forms an address, which address
> needs to be implicitly dereferenced to get a value, or which in
> certain cases may be used to store a value into an object at
> that address).
I do not know whether this comment is indeed true. I am not going to
read the complete standard now. But *when* an lvalue that is not an
object type is evaluated, the result is UB.


Are you confusing the two concepts? Having object type is a
static property of expressions; whether the result of an
evaluation designates an object is a run-time property of the
value of an expression's evaluation. Almost all expressions
that are lvalues have object type; the exceptions are things
like array names of unknown length and a few other things that
people hardly ever write in actual programs.

Which means that an evaluatable lvalue is precisely
what you describe. [snip]
First let me distinguish two terms. An lvalue(S) is an
lvalue as it is defined in the standard. An lvalue(U) is
an lvalue as understood by most CLC regulars and by all
the implementations I'm familiar with.

Using that terminology, what you're saying is that I'm
describing an evaluatable lvalue(S).

My intention was to describe an lvalue(U); whether that
corresponds to an evaluatable lvalue(S) depends on what's
meant by "evaluatable". There is nothing in my description of
lvalue(U) that says the address will actually designate an
object; eg, '* (char*) 0' is an lvalue(U), but it does not
designate an object.

Not counting that minor point though I think your point is
correct: an lvalue(U) corresponds to an lvalue(S) for which
evaluation is plausible.

> Why do people (including myself) think this? Various statements
> in sections 6.5.x that certain kinds of expressions -- but not
> all expressions with object type -- are lvalues;


Pray provide a reference. I have looked through the draft and did
not find any such statements. [...also for footnotes...]


The index for "lvalue" shows 6.5.1, 6.5.2.4, 6.5.3.1, and
6.5.16. The footnotes include numbers 95, 92 and 94; I
believe these numbers correspond to numbers 76, 83 and 85 in
N869. I'm pretty sure this list isn't complete; I haven't
attempted to do any kind of exhaustive search.

> Other related comments also; for
> example, in talking about the address-of operator, 6.5.3.2 says
> the operand of '&' shall be (other unrelated stuff or) an
> lvalue (that isn't a register or referring to a bit-field).
> Clearly this restriction isn't meant to allow all expressions
> of object type: the expression
> &(a+b)
> is nonsense.


Depends on the types of a and b.


Actually I think the expression '&(a+b)' is nonsense no matter
what the types of a and b are.

But when they are (say) integer
variables, the expression is indeed an lvalue.
The expression '(a+b)' is an lvalue(S). It is not an
lvalue(U).

But the address
operator requires evaluation, and there you are. UB, because there
is not an object.


Consider this expression:

sizeof &(a+b)

Assuming no variable length arrays, there is no evaluation of
the address operator; however, the expression is still
illegal:
$ cat lvalue.c
void
foo(){
int a, b;
sizeof &(a+b);
}

$ gcc -ansi -pedantic lvalue.c
lvalue.c: In function `foo':
lvalue.c:4: invalid lvalue in unary `&'

$ gcc -std=c99 -pedantic lvalue.c
lvalue.c: In function `foo':
lvalue.c:4: invalid lvalue in unary `&'
Nov 15 '05 #199
Keith Thompson wrote:
"Dik T. Winter" <Di********@cwi.nl> writes:

<snip>
But there is a sentence following it:
"if an lvalue does not designate an object when it is evaluated, the
behavior is undefined."
So, while the constant 42 is of an object type, it is not an object, and
any use as an lvalue will result in undefined behaviour.


You say "any use *as an lvalue*". The standard says the behavior is
undefined *when it is evaluated*; it doesn't say "as an lvalue".

An lvalue is a kind of expression (all lvalues are expressions; not all
expressions are lvalues). If 42 is an lvalue, then it is evaluated in

int x;
x = 42;

and a literal reading of the standard implies that this evaluation
invokes undefined behavior.


I hadn't noticed that before but you're right.

It is possible to argue that since the concept of lvalue is so broadly
defined, the standard must specify separately for each expression
whether it is an lvalue or not, and by that reasoning whether or not a
constant is an lvalue would be unspecified. I prefer your reasoning
though since it "catches" unspecified expressions (albeit detrimentally
in this case).
> Why do people (including myself) think this? Various statements
> in sections 6.5.x that certain kinds of expressions -- but not
> all expressions with object type -- are lvalues;


Pray provide a reference. I have looked through the draft and did
not find any such statements.

<snip>
> and, footnotes
> here and there that other kinds of expressions (still with
> object type) are not lvalues.


Again, pray provide references.


I've put together a comprehensive list by searching for the string
"lvalue" in N869, starting at the beginning and stopping at the
annexes. I posted it recently in a separate thread but obviously you
didn't see that post.

lvalues:
6.5.1#2 an identifier declared as designating an object
6.5.1#4 a string literal
6.5.1#5 a parenthesized expr if the unparenthezised expr is an lvalue
6.5.2.3#3 struct expression members accessed with "." if the struct
expression is an lvalue
6.5.2.3#4 struct expression members accessed with "->"
6.5.2.5#5 a compound literal
6.5.3.2#4 the result of "*" if the operand points to an object
7.5#2 errno

non-lvalues:
6.5.3.2#3 the result of "&*"
6.5.16#3 an assignment expression
Non-normative footnotes: cast, comma and conditional expressions

The footnotes are 76, 83 and 85 in the draft I use:
http://dev.unicals.com/papers/c99-draft.html

Also I've updated and rewritten my summary of "the lvalue situation"
which includes the above list and is mostly a distillation of the
relevant parts of this thread. You may find it easier to process than
rereading this scattered and messy thread:
http://members.dodo.com.au/~netocrat/c/lvalue.html

<snip rest of Keith's reply, which I endorse>

Nov 15 '05 #200

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: pemo | last post by:
I've just been trying out the Watcom compiler from http://www.openwatcom.org, and almost immediately compiled some working source that errored. The code is char buffer; ...
34
by: thibault.langlois | last post by:
Hello, I get a warning when I compile: #include <string.h> int main (int argc, char ** argv) { char * s; s = strdup("a string"); return 0; }
7
by: vippstar | last post by:
Today I got a confusing message from gcc (I'm aware, those don't break conformance ;-) In function 'main': 7: warning: format '%d' expects type 'int', but argument 2 has type 'char (*)' The...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.