Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

pointers one past the end of an array still not fixed

17 views
Skip to first unread message

Michael Norrish

unread,
Jan 16, 1998, 3:00:00 AM1/16/98
to

The draft says that

If two pointers to object or incomplete types compare equal, they
both are null pointers, or both point to the same object, or both
point one past the last element of the same array object. (6.3.9)

This forbids implementations from printing one in the following
program:

#include <stdio.h>

int main(void)
{
int x;
int y;
int *yptr = &y;
printf("%d\n", yptr == &x + 1);
return 0;
}

The language needlessly makes implementations non-conforming.

To reflect the reality of implementations' behaviour, you might change
the last clause to: "or either points one past the last element of an
array object".

Michael.


Clive D.W. Feather

unread,
Jan 16, 1998, 3:00:00 AM1/16/98
to

In article <yvsiurk...@merganser.cl.cam.ac.uk>, Michael Norrish
<mn...@cl.cam.ac.uk> writes

>The draft says that
> If two pointers to object or incomplete types compare equal, they
> both are null pointers, or both point to the same object, or both
> point one past the last element of the same array object. (6.3.9)

Already on my issues list.

--
Clive D.W. Feather | Director of Software Development | Home email:
Tel: +44 181 371 1138 | Demon Internet Ltd. | <cl...@davros.org>
Fax: +44 181 371 1037 | <cl...@demon.net> |
Written on my laptop; please observe the Reply-To address |

Valentin Bonnard

unread,
Jan 16, 1998, 3:00:00 AM1/16/98
to Clive D.W. Feather

Clive D.W. Feather <cl...@on-the-train.demon.co.uk> writes:

> In article <yvsiurk...@merganser.cl.cam.ac.uk>, Michael Norrish
> <mn...@cl.cam.ac.uk> writes
> >The draft says that
> > If two pointers to object or incomplete types compare equal, they
> > both are null pointers, or both point to the same object, or both
> > point one past the last element of the same array object. (6.3.9)
>
> Already on my issues list.

This has been discussed in comp.lang.c++.moderated and is
wrong; the wording doesn't need to be fixed. (At least not
here.)

All it says is that: ptr equalty implies thing equalty
where 'thing' mean object or non-object (one-past-the-end
isn't an object)

It doesn't say that thing difference implies ptr difference,
that is, the above text doesn't say that pointers to
different objects compare unequal. If you only keep the
above text in the std (ie remove everything else), an
implementation printing 'equal' is conforming:

int main ()
{
int a, b;
printf (&a == &b ? "equal" : "not equal");
return 0;
}

MN = Michael Norrish
MN> int main(void)
MN> {
MN> int x;
MN> int y;
MN> int *yptr = &y;
MN> printf("%d\n", yptr == &x + 1);
MN> return 0;
MN> }

Here yptr and &x + 1 both point one past the end the same
array x, and both point to y. A pointer can point to two
different things.

--

Valentin Bonnard mailto:bonn...@pratique.fr
info about C++/a propos du C++: http://www.pratique.fr/~bonnardv/

Bradd W. Szonye

unread,
Jan 16, 1998, 3:00:00 AM1/16/98
to

Valentin Bonnard wrote in message <34BFAC...@pratique.fr>...

>Clive D.W. Feather <cl...@on-the-train.demon.co.uk> writes:
>
>> In article <yvsiurk...@merganser.cl.cam.ac.uk>, Michael Norrish
>> <mn...@cl.cam.ac.uk> writes
>> >The draft says that
>> > If two pointers to object or incomplete types compare equal, they
>> > both are null pointers, or both point to the same object, or both
>> > point one past the last element of the same array object. (6.3.9)
>>
>> Already on my issues list.
>
>This has been discussed in comp.lang.c++.moderated and is
>wrong; the wording doesn't need to be fixed. (At least not
>here.)

I thought the similar discussion in clc.mod was about different verbiage. In
particular, I remember "if and only if" appearing in that discussion, which
isn't in the text above.

In any case, I read the proposed revised verbiage on Mr. Feather's page, and
I like it better than any definition of pointer equality I've seen before.
It spells all the cases out explicitly, even to say when equality is
unspecified.
---
Bradd W. Szonye
bra...@concentric.net
http://www.concentric.net/~Bradds

Dave Hansen

unread,
Jan 17, 1998, 3:00:00 AM1/17/98
to

On Fri, 16 Jan 1998 19:52:14 +0100, Valentin Bonnard
<bonn...@pratique.fr> wrote:

>Clive D.W. Feather <cl...@on-the-train.demon.co.uk> writes:
>
>> In article <yvsiurk...@merganser.cl.cam.ac.uk>, Michael Norrish
>> <mn...@cl.cam.ac.uk> writes
>> >The draft says that
>> > If two pointers to object or incomplete types compare equal, they
>> > both are null pointers, or both point to the same object, or both
>> > point one past the last element of the same array object. (6.3.9)
>>
>> Already on my issues list.
>
>This has been discussed in comp.lang.c++.moderated and is
>wrong; the wording doesn't need to be fixed. (At least not
>here.)
>

>All it says is that: ptr equalty implies thing equalty
>where 'thing' mean object or non-object (one-past-the-end
>isn't an object)
>
>It doesn't say that thing difference implies ptr difference,
>that is, the above text doesn't say that pointers to
>different objects compare unequal. If you only keep the

But it does. It says "if two pointers compare equal, They are either
both NULL, both point to the same object, or both point one past the
end of the same array" (my paraphrase). If these are the only cases
in which pointers may compare equal, then in all other cases they must
compare not equal. Given

int x, y, *p1=(&x+1), *p2=&y;

then p1 and p2 better not compare equal, because none of the three
conditions are met.

Mr. Norrish's suggestion would change the last condition to allow one
of the pointers to point to an object and the other to point one past
the end of an array 'and still compare equal.



>above text in the std (ie remove everything else), an
>implementation printing 'equal' is conforming:
>
>int main ()
>{
> int a, b;
> printf (&a == &b ? "equal" : "not equal");
> return 0;
>}

Why? Because &b points one past the end of an array? I'm not sure
that argument is valid -- &b points to b, &a points to a, neither is
NULL or points one past any array. Since none of the three conditions
are met, the pointers must not compare equal.

The following case is more interesting:

int main()
{
int a, b, c;

printf(&b == &a+1? "equal, ": "not equal, ");
printf(&c == &a+1? "equal\n": "not equal\n");

return 0;
}

Would Mr. Norrish's suggestion allow a conforming implementation to
print "equal, equal"? I think so. Not that any one would. But I can
see how this is a sticky problem...

Regards,

-=Dave
dha...@btree.com
Just my (10 - 010) cents worth.
I can barely speak for myself, so I certainly can't speak for B-Tree.

Valentin Bonnard

unread,
Jan 17, 1998, 3:00:00 AM1/17/98
to Dave Hansen

Dave Hansen <dha...@btree.com> writes:

> On Fri, 16 Jan 1998 19:52:14 +0100, Valentin Bonnard
> <bonn...@pratique.fr> wrote:
>
> >All it says is that: ptr equalty implies thing equalty
> >where 'thing' mean object or non-object (one-past-the-end
> >isn't an object)
> >
> >It doesn't say that thing difference implies ptr difference,
> >that is, the above text doesn't say that pointers to
> >different objects compare unequal. If you only keep the
>
> But it does.

No it doesn't.

> It says "if two pointers compare equal, They are either
> both NULL, both point to the same object, or both point one past the
> end of the same array" (my paraphrase). If these are the only cases
> in which pointers may compare equal, then in all other cases they must
> compare not equal. Given
>
> int x, y, *p1=(&x+1), *p2=&y;
>
> then p1 and p2 better not compare equal, because none of the three

^^^^^
> conditions are met.
^^^^^^^^^^^^^^^^^^

How do you know that p1 doesn't point one past an array ?

> Mr. Norrish's suggestion would change the last condition to allow one
> of the pointers to point to an object and the other to point one past
> the end of an array 'and still compare equal.

He is assuming that there is a function

dereference: pointer -> object U one-past-the-end U undefined

which for each pointer value gives the unique thing to
which it points. My understanding (until someone show me
std wording to this effect) is that there is no such function.

> >above text in the std (ie remove everything else), an
> >implementation printing 'equal' is conforming:
> >
> >int main ()
> >{
> > int a, b;
> > printf (&a == &b ? "equal" : "not equal");
> > return 0;
> >}
>
> Why? Because &b points one past the end of an array? I'm not sure
> that argument is valid -- &b points to b, &a points to a, neither is
> NULL or points one past any array. Since none of the three conditions
> are met, the pointers must not compare equal.

You assume here that &a doesn't point to b; nothing in
the above text says that _unless_ another part of the
std saves you by saying that two objects may not be at
the same address. (Or &a and &b might both point one
past the array {'e','q','u','a','l','0'}.)

The problem is the existance of the above dereference
application, or in other words the fact that 'p points
to a and p points to b' where a and b are differents
things (ie object or one-past-the-end) is contradicting.

David Adrien Tanguay

unread,
Jan 17, 1998, 3:00:00 AM1/17/98
to

Dave Hansen wrote:
> >> > If two pointers to object or incomplete types compare equal, they
> >> > both are null pointers, or both point to the same object, or both
> >> > point one past the last element of the same array object. (6.3.9)
> compare not equal. Given
>
> int x, y, *p1=(&x+1), *p2=&y;
>
> then p1 and p2 better not compare equal, because none of the three
> conditions are met.

But p1 does point to an object. It also points one past the end of an
array. Is there something that says every pointer must have uniquely one
of the three qualities? Or that the qualities only apply from a strict
interpretation of the abstract machine?
--
David Tanguay d...@Thinkage.on.ca http://www.thinkage.on.ca/~dat/
Thinkage, Ltd. Kitchener, Ontario, Canada [43.24N 80.29W]

Christian Bau

unread,
Jan 19, 1998, 3:00:00 AM1/19/98
to

In article <Qlmd9BAc...@romana.davros.org>, "Clive D.W. Feather"
<cl...@demon.net> wrote:

> In article <yvsiurk...@merganser.cl.cam.ac.uk>, Michael Norrish
> <mn...@cl.cam.ac.uk> writes
> >The draft says that

> > If two pointers to object or incomplete types compare equal, they
> > both are null pointers, or both point to the same object, or both
> > point one past the last element of the same array object. (6.3.9)
>

> Already on my issues list.

I think what is needed is an addition to the standard that says something like

"A pointer that points one past the last element of an array element
may by coincidence also point to the first element of another object". So
if I write

struct { int a; int b; int c; } x;
int y;

then
&x.a + 1 == &x.b; // May be true by coincidence
&x.a + 1 == &x.c; // This cannot be true.
&x.a + 1 == &y; // This cannot be true.
&x.c + 1 == &y; // May be true by coincidence
&y + 1 == &x.a; // May be true by coincidence

Michael Norrish

unread,
Jan 19, 1998, 3:00:00 AM1/19/98
to

Valentin Bonnard <bonn...@pratique.fr> writes:

> Dave Hansen <dha...@btree.com> writes:

> > On Fri, 16 Jan 1998 19:52:14 +0100, Valentin Bonnard
> > <bonn...@pratique.fr> wrote:

> > >All it says is that: ptr equalty implies thing equalty
> > >where 'thing' mean object or non-object (one-past-the-end
> > >isn't an object)

> > >It doesn't say that thing difference implies ptr difference,
> > >that is, the above text doesn't say that pointers to
> > >different objects compare unequal. If you only keep the

> > But it does.

> No it doesn't.

> > It says "if two pointers compare equal, They are either
> > both NULL, both point to the same object, or both point one past the
> > end of the same array" (my paraphrase). If these are the only cases
> > in which pointers may compare equal, then in all other cases they must

> > compare not equal. Given
> >
> > int x, y, *p1=(&x+1), *p2=&y;
> >
> > then p1 and p2 better not compare equal, because none of the three

> ^^^^^
> > conditions are met.
^^^^^^^^^^^^^^^^^^

> How do you know that p1 doesn't point one past an array ?

p1 does point one past the end of an array. It points one past the
end of the array corresponding to x. However, &p2 can not be such a
pointer, because it must be defined behaviour to dereference it (once
y is initialised anyway!), and it is undefined behaviour to
dereference a pointer one past the end of an array. So, while p1 is a
pointer one past the end of an array, p2 is not so they shouldn't
compare equal.

Clive's suggested wording on his public comment page is a big
improvement.

Michael.

Clive D.W. Feather

unread,
Jan 19, 1998, 3:00:00 AM1/19/98
to

In article <34C02E...@pratique.fr>, Valentin Bonnard
<bonn...@pratique.fr> writes

>You assume here that &a doesn't point to b; nothing in
>the above text says that _unless_ another part of the
>std saves you by saying that two objects may not be at
>the same address.

C9X has wording saying that (6.1.2.4; also see FN24). There are explicit
exceptions for string literals and for const compound literals (yes, I
know there is a thread on this going on).

I've reworded my proposal on this rewording after reading this
discussion and some other email.

David E. Wallace

unread,
Jan 20, 1998, 3:00:00 AM1/20/98
to

In article <34C02E...@pratique.fr>,
Valentin Bonnard <bonn...@pratique.fr> wrote:

:Dave Hansen <dha...@btree.com> writes:
:> On Fri, 16 Jan 1998 19:52:14 +0100, Valentin Bonnard
:> <bonn...@pratique.fr> wrote:

:> >All it says is that: ptr equalty implies thing equalty
:> >where 'thing' mean object or non-object (one-past-the-end
:> >isn't an object)

:> >It doesn't say that thing difference implies ptr difference,
:> >that is, the above text doesn't say that pointers to
:> >different objects compare unequal. If you only keep the

:> But it does.

:No it doesn't.

Sure it does: not explicitly, but by the Law of Contrapositives,
a basic principle of logical reasoning. The law says that if
p implies q, then (NOT q) implies (NOT p), and vice-versa.
So if ptr equality implies thing equality, then (NOT thing equality)
implies (NOT ptr equality), or in other words, thing difference
implies ptr difference. Logically it's the same thing, just
expressed differently.
--
Dave Wallace (wal...@netcom.com)
It is quite humbling to realize that the storage occupied by the longest
line from a typical Usenet posting is sufficient to provide a state space
so vast that all the computation power in the world can not conquer it.

Valentin Bonnard

unread,
Jan 20, 1998, 3:00:00 AM1/20/98
to David E. Wallace

David E. Wallace <wal...@netcom.com> writes:

> In article <34C02E...@pratique.fr>,
> Valentin Bonnard <bonn...@pratique.fr> wrote:
> :Dave Hansen <dha...@btree.com> writes:
> :> On Fri, 16 Jan 1998 19:52:14 +0100, Valentin Bonnard
> :> <bonn...@pratique.fr> wrote:
>
> :> >All it says is that: ptr equalty implies thing equalty
> :> >where 'thing' mean object or non-object (one-past-the-end
> :> >isn't an object)
>
> :> >It doesn't say that thing difference implies ptr difference,
> :> >that is, the above text doesn't say that pointers to
> :> >different objects compare unequal. If you only keep the
>
> :> But it does.
>
> :No it doesn't.
>
> Sure it does: not explicitly, but by the Law of Contrapositives,
> a basic principle of logical reasoning. The law says that if
> p implies q, then (NOT q) implies (NOT p), and vice-versa.
> So if ptr equality implies thing equality, then (NOT thing equality)
> implies (NOT ptr equality), or in other words, thing difference
> implies ptr difference. Logically it's the same thing, just
> expressed differently.

But you elided the text explaning why it doesn't follow.

I can rewrite it logically if you prefer:

The above elided std sentence says:

p == q and p and q are non null pointers => there exist
a thing T such as p points to T and q points to T (a)

_not_ that

there exist two different things T and U such as p points to T
and p points to U => not (p == q) (b)

In other words I am claiming that a pointer can point to two
differents objects, until someone prove me the contrary with
an extract of the std. Arguments such as: 'if you are right,
then any pointer dereference is undefined behaviour' aren't
valid. Who told you that evaluating *p could have a
well-defined behaviour ?

BTW: in the std (assuming no undefined behaviour), (b) => (a),
because if p is a non-null pointer, then p points to something
(at least I think so).

BTW: the C std is everything but a logicall theory, so
either fix it or don't reson mathematically in it.

James Kuyper

unread,
Jan 20, 1998, 3:00:00 AM1/20/98
to

Valentin Bonnard wrote:
>
> David E. Wallace <wal...@netcom.com> writes:
>
> > In article <34C02E...@pratique.fr>,
> > Valentin Bonnard <bonn...@pratique.fr> wrote:
...

> > a basic principle of logical reasoning. The law says that if
> > p implies q, then (NOT q) implies (NOT p), and vice-versa.
> > So if ptr equality implies thing equality, then (NOT thing equality)
> > implies (NOT ptr equality), or in other words, thing difference
> > implies ptr difference. Logically it's the same thing, just
> > expressed differently.
>
> But you elided the text explaning why it doesn't follow.
>
> I can rewrite it logically if you prefer:
>
> The above elided std sentence says:
>
> p == q and p and q are non null pointers => there exist
> a thing T such as p points to T and q points to T (a)

False; what it actually says is:

IF p==q THEN ( (p==NULL && q==NULL) || (p and q point to same object) ||
(p and q both point to 1 past end of same array) )

There are three different statements at issue, involving four basic
propositions:
A: p==q
B: p==NULL && q==NULL
C: p and q point to same object
D: p and q both point to 1 past the end of the same array


1. IF A THEN (B OR C OR D) /* The standard's wording. */

2. IF (A AND NOT B) THEN (C OR D) /* Your re-wording. */

3. IF NOT (B OR C OR D) THEN NOT A
/* roughly: non-NULL pointers that don't point to the same
object do not compare equal. */

(1) implies (2), but (2) does not imply (3); for that matter, (2) does
not imply (1). The important point is that (1) does imply (3), so all
three statements are true.

Henning Makholm

unread,
Jan 20, 1998, 3:00:00 AM1/20/98
to

James Kuyper <kuy...@wizard.net> writes:

> 1. IF A THEN (B OR C OR D) /* The standard's wording. */
>
> 2. IF (A AND NOT B) THEN (C OR D) /* Your re-wording. */
>
> 3. IF NOT (B OR C OR D) THEN NOT A
> /* roughly: non-NULL pointers that don't point to the same
> object do not compare equal. */

> (1) implies (2), but (2) does not imply (3);

Yes it does. In fact, in classical logic all three formulas are
equivalent (and I think they are in abstract Boolean algebra,
too). Try sketching up a truth table.

Actually the claim whose falsehhod Valentin, in his latest article,
proposes is neither of the three. But I still do not understand how he
got from "thing difference does not imply pointer difference" to what
he is saying now.

--
Henning Makholm
http://www.diku.dk/students/makholm

Douglas A. Gwyn

unread,
Jan 21, 1998, 3:00:00 AM1/21/98
to

In article <34C4CC...@pratique.fr>,

Valentin Bonnard <bonn...@pratique.fr> wrote:
>In other words I am claiming that a pointer can point to two
>differents objects, ...

What a pointer points to is determined by two things:
its type
its value

The object pointed to by a valid non-null value of a pointer
which has type "pointer to T", where T is some object type,
is uniquely determined by the value and type. (The only
exception occurs when the pointed-to object is cached in an
aliased variable, but that is a minor, very obscure issue.)

Objects clearly can overlap, and pointers to objects of
different types might appear to have the same "value"
(although by the time you transform them in a strictly
conforming manner to compare them, they should be pointers
to compatible types and thus everything should work out).
However, pointers *of the same type* cannot have the same
value yet point to nonidentical objects (apart from the
aforementioned aliasing issue).

I don't think the C standard has ever gotten this part of
the language specification quite right. It has tried to
specify a small number of properties from which the rest
of the properties of pointer comparison could be logically
derived, but the properties it picked don't seem to have
been the most fundamental ones.


Dennis Yelle

unread,
Jan 21, 1998, 3:00:00 AM1/21/98
to

In article <6a43hd$5...@dfw-ixnews11.ix.netcom.com> Douglas A. Gwyn <gw...@ix.netcom.com> writes:
>In article <34C4CC...@pratique.fr>,
> Valentin Bonnard <bonn...@pratique.fr> wrote:
>>In other words I am claiming that a pointer can point to two
>>differents objects, ...
>
>What a pointer points to is determined by two things:
> its type
> its value
>
>The object pointed to by a valid non-null value of a pointer
>which has type "pointer to T", where T is some object type,
>is uniquely determined by the value and type. (The only
>exception occurs when the pointed-to object is cached in an
>aliased variable, but that is a minor, very obscure issue.)

You have ignored the basic "problem" pointed out in other
postings in this thread:

In the simple case of:

int a[2], b;
int *pa = &a[1];
int *pb = &b;
pa++;

if ( pa == pb ) printf( "They are equal.\n");

I believe, and I think that most experienced C programmers believe,
that it is possible for a conforming implementation to print
"They are equal.\n", in the case above. Further,
I believe that many existing implementations print "They are equal.\n"
in this case and/or in similar cases.
(Consider also: struct stuff { int a[2]; int b; };)
But, I also believe that there are some people that think
that this is ruled out by the words of the standard, or
that it _should be_ ruled out by the words of the standard.

The problem is that pa is allowed to point
one past the end of a. But, I guess, if it does point
one past the end of a, it is not considered to be pointing to an
object. Even if pa, by coincidence, has the correct value and
type to be pointing at b, and (pa == pb) is true.

Dennis Yelle

--
den...@netcom.com (Dennis Yelle)
"You must do the thing you think you cannot do." -- Eleanor Roosevelt

Scott Mayo

unread,
Jan 21, 1998, 3:00:00 AM1/21/98
to

Can pointers to two different, non-const objects, not involving any pointer
arithmetic, ever compare equal in a conforming implementation? I don't mean two
elements in a union, I mean truly separate objects, possibly of different
types (cast to void* as needed).

Douglas A. Gwyn

unread,
Jan 21, 1998, 3:00:00 AM1/21/98
to

Dennis Yelle wrote:
> You have ignored the basic "problem" pointed out in other
> postings in this thread:

No, "Mu!"

I haven't ignored the problem, because people have been (again)
confusing *themselves* by misanalysis. That's why I posted the
explanation I did; once you correctly understand object access
via pointers, there should be no further confusion.

> int a[2], b;
> int *pa = &a[1];
> int *pb = &b;
> pa++;
> if ( pa == pb ) printf( "They are equal.\n");
> I believe, and I think that most experienced C programmers believe,
> that it is possible for a conforming implementation to print
> "They are equal.\n", in the case above.

Of course, because pa and pb would point to the same object
in such implementations, where the storage for a and b abut.

> But, I also believe that there are some people that think
> that this is ruled out by the words of the standard, or
> that it _should be_ ruled out by the words of the standard.

Undoubtedly there are a lot of confused people in the world.

> The problem is that pa is allowed to point
> one past the end of a. But, I guess, if it does point
> one past the end of a, it is not considered to be pointing to an
> object.

No, there you go again, confusing yourself. It does (accidentally)
point to an object in such implementations as we have just been
discussing, although the standard cannot *guarantee* that it
points to an object. (In some implementations, it won't.)
However, the *value* of such a pointer *is* guaranteed to be valid,
you just cannot dereference it in a strictly conforming program;
you can still use this pointer value in certain contexts spelled
out in the standard. The reason for all this, of course, is to
facilitate the use of pointers when walking through arrays.
(This is sufficiently strong motivation that there has been an
attempt in the C9x draft to legitimatize the expression &a[2],
which we believe was not strictly conforming according to C89,
although the expression a+2 *is* strictly conforming.)

Valentin Bonnard

unread,
Jan 22, 1998, 3:00:00 AM1/22/98
to Scott Mayo

Scott Mayo <sm...@ziplink.net> writes:

> Can pointers to two different, non-const objects, not involving any

^^^^^^^^^


> pointer arithmetic, ever compare equal in a conforming implementation? I
> don't mean two elements in a union, I mean truly separate objects,
> possibly of different types (cast to void* as needed).

This has nothing (and shouldn't have anything) to do with const.

And the std should answer no, but only a C expert could confirm.

Peter Seebach

unread,
Jan 22, 1998, 3:00:00 AM1/22/98
to

In article <34C68287...@arl.mil>, Douglas A. Gwyn <gw...@arl.mil> wrote:
>> int a[2], b;
>> int *pa = &a[1];
>> int *pb = &b;
>> pa++;
>> if ( pa == pb ) printf( "They are equal.\n");
>> I believe, and I think that most experienced C programmers believe,
>> that it is possible for a conforming implementation to print
>> "They are equal.\n", in the case above.

>Of course, because pa and pb would point to the same object
>in such implementations, where the storage for a and b abut.

That's not an object! pa does not point to b; we know this, because
it is a valid pointer not derived from b.

Of course, it turns out that what we know is wrong - but the standard
does seem to state (in its current form) that pa and pb must be distinct,
because, after all, they are derived from different objects.

>(This is sufficiently strong motivation that there has been an
>attempt in the C9x draft to legitimatize the expression &a[2],
>which we believe was not strictly conforming according to C89,
>although the expression a+2 *is* strictly conforming.)

"we" may be a bit strong. I agree with you on this one - I don't
think &a[2] is strictly conforming - but several people have argued
that it is. I don't follow the argument, but it basically says
that '*' doesn't really happen until you *use* the value.

-s
--
se...@plethora.net -- I am not speaking for my employer. Copyright '97
All rights reserved. Boycott Spamazon! End Spam. C and Unix wizard -
send mail for help, or send money for a consultation. Visit my new ISP
<URL:http://www.plethora.net/> --- More Net, Less Spam! Plethora . Net

Douglas A. Gwyn

unread,
Jan 22, 1998, 3:00:00 AM1/22/98
to

In article <6a6b0j$oa0$2...@darla.visi.com>,

se...@plethora.net (Peter Seebach) wrote:
>That's not an object!

Oh, yes it is, *in the postulated implementation*.
(It's a region of storage capable of representing a value.)

A *strictly conforming* program cannot assume it is an object, however,
because sometimes there isn't one there, and the standard tries to
word things delicately so that the pointer value has meaning even if
there is no object pointed to (and of course also if there is!).

>Of course, it turns out that what we know is wrong - but the standard
>does seem to state (in its current form) that pa and pb must be distinct,
>because, after all, they are derived from different objects.

I recall no notion in the standard of "derived from different objects".
There is a list of what can cause two pointers to compare equal,
including both pointing to the same object or both pointing just
past the last element of the same array object (there may not be an
object there, which is why this has to be enumerated separately).

In the case we were discussing, two pointers compare equal because
they *accidentally* point to the same object. I don't see that as
a problem. (It is awareness that such things can happen that led
us to conclude that each successful invocation malloc(0) without
intervening free() of the returned pointers, must take special
steps to arrange for distinct pointers to be returned; otherwise,
e.g. with a "buddy system" allocator, the convenience of allowing
0-sized allocations could be lost by the need for the application
to watch out for this when comparing pointers for "points to the
same allocated node".)

>>(This is sufficiently strong motivation that there has been an
>>attempt in the C9x draft to legitimatize the expression &a[2],
>>which we believe was not strictly conforming according to C89,
>>although the expression a+2 *is* strictly conforming.)
>"we" may be a bit strong. I agree with you on this one - I don't
>think &a[2] is strictly conforming - but several people have argued
>that it is. I don't follow the argument, but it basically says
>that '*' doesn't really happen until you *use* the value.

Well, I was one of the DR response subgroup members who tracked
down the logic step by step and concluded that a literal reading
of the C89 standard could require &a[2] to generate a diagnostic,
since it is a constraint violation (6.3.3.2): a[2] is definitely
*not necessarily* "an lvalue that designates an object". The
problem is, it *might* accidentally designate an object on some
implementations, and whether or not it does *might* not be
determinable until run time. There is thus a definite problem
with the C89 wording in 6.3.3.2 (Address and indirection
operators), but this lack of distinction between there *being*
an object and there *being guaranteed (by the standard) to be*
an object is making it hard to get the words right. There has
been (in working on the C9x draft) some attempt to redefine
"lvalue"ness in an attempt to solve such problems, but I think
we're shining light in the wrong place.


Hallvard B Furuseth

unread,
Jan 22, 1998, 3:00:00 AM1/22/98
to

Douglas A. Gwyn <gw...@ix.netcom.com> writes:

> this lack of distinction between there *being*
> an object and there *being guaranteed (by the standard) to be*
> an object is making it hard to get the words right. There has
> been (in working on the C9x draft) some attempt to redefine
> "lvalue"ness in an attempt to solve such problems, but I think
> we're shining light in the wrong place.

Would it help to define a two kinds of objects - `formal' and `physical'
objects? `==' would talk about physical objects, most other things
would talk about formal objects. Maybe this would also handle the
problem with folded literals (that compare equal) given as arguments to
`restrict' parameters.

(Details: Two string literals would be different formal objects but
might be the same physical object. Any physical objects that happen to
be next to each other in memory would probably by definition comprise a
bigger physical object. I'm not quite sure how to classify padding
bytes *inside* physical objects (structs), though).

--
Hallvard

Dave Hansen

unread,
Jan 22, 1998, 3:00:00 AM1/22/98
to

On Wed, 21 Jan 1998 16:44:38 -0500, sm...@ziplink.net (Scott Mayo)
wrote:

>Can pointers to two different, non-const objects, not involving any pointer

>arithmetic, ever compare equal in a conforming implementation? I don't mean two
>elements in a union, I mean truly separate objects, possibly of different
>types (cast to void* as needed).

I believe (I'm sure someone will correct me if I'm wrong :) That the
following code:

struct {int x, y;} s, *ps=&s;
int *pi = &s.x;
void *p1=ps, *p2=pi;

printf("The pointers are %s\n", (p1==p2? "equal.": "not equal."));

is guaranteed to print "The pointers are equal." I would say that ps
and pi point to two different objects (a struct and an int
respectively). Whether that meets your definition of "truly separate
objects" may be another matter...

Julian Pardoe

unread,
Jan 22, 1998, 3:00:00 AM1/22/98
to

In article <34C68287...@arl.mil>, gw...@arl.mil (Douglas A. Gwyn)
wrote:

> (This is sufficiently strong motivation that there has been an
> attempt in the C9x draft to legitimatize the expression &a[2],
> which we believe was not strictly conforming according to C89,
> although the expression a+2 *is* strictly conforming.)

As a person who writes &a[i] when I mean the "address of the i'th
element of a" I am surprised and upset to learn that (in this example)
&a[2] isn't conforming but a+2 is.

In any case I thought a[i] and *(a+i) were defined to be equivalent and
so would expect &a[i] and &(*(a+i)) to be equivalent.

-- jP --

marty Holcomb

unread,
Jan 23, 1998, 3:00:00 AM1/23/98
to

Julian Pardoe wrote:
>In any case I thought a[i] and *(a+i) were defined to be equivalent and
>so would expect &a[i] and &(*(a+i)) to be equivalent.
>
Could it be that a[i] and *(a+i) are equivalent and &(a[i]) and &(*(a+i))
are equivalent?


Lawrence Kirby

unread,
Jan 23, 1998, 3:00:00 AM1/23/98
to

In article <34c78178...@192.168.2.34>
dha...@btree.com "Dave Hansen" writes:

>On Wed, 21 Jan 1998 16:44:38 -0500, sm...@ziplink.net (Scott Mayo)
>wrote:
>
>>Can pointers to two different, non-const objects, not involving any pointer
>>arithmetic, ever compare equal in a conforming implementation? I don't mean two>>elements in a union, I mean truly separate objects, possibly of different
>>types (cast to void* as needed).
>
>I believe (I'm sure someone will correct me if I'm wrong :) That the
>following code:
>
> struct {int x, y;} s, *ps=&s;
> int *pi = &s.x;
> void *p1=ps, *p2=pi;
>
> printf("The pointers are %s\n", (p1==p2? "equal.": "not equal."));
>
>is guaranteed to print "The pointers are equal." I would say that ps
>and pi point to two different objects (a struct and an int
>respectively). Whether that meets your definition of "truly separate
>objects" may be another matter...

This boils down to the definition of "object". Section 3.14 of C90 (and
section 3.15 of the correct C9X draft) say:

"object: A region of data storage in the execution environment, the contents
of which can represent values. .... When referenced, an object may be
interpreted as having a particular type: see 6.2.2.1"

So type isn't an inherent property of an object (just think of malloc'd
objects); you can access the same object (or parts of the same object)
using lvaues of different types. It is better to talk about distinct (i.e.
non-overlapping) objects rather than different objects. Pointers to distinct
objects (right down to the individual bytes which can be considered as
separate objects) should compare unequal. You just need to take care about
the sort of pointer conversions you use to facilitate the comparison; if
the pointer conversion results in undefined behaviour (e.g. for alignment
reasons) then all bets are off.

--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------


James Kuyper

unread,
Jan 23, 1998, 3:00:00 AM1/23/98
to

Julian Pardoe wrote:
>
> In article <34C68287...@arl.mil>, gw...@arl.mil (Douglas A. Gwyn)
> wrote:
>
[referring to an array declared as int a[1]; ]

> > (This is sufficiently strong motivation that there has been an
> > attempt in the C9x draft to legitimatize the expression &a[2],
> > which we believe was not strictly conforming according to C89,
> > although the expression a+2 *is* strictly conforming.)
>
> As a person who writes &a[i] when I mean the "address of the i'th
> element of a" I am surprised and upset to learn that (in this example)
> &a[2] isn't conforming but a+2 is.
>
> In any case I thought a[i] and *(a+i) were defined to be equivalent and
> so would expect &a[i] and &(*(a+i)) to be equivalent.

My understanding is that &a[i] and &(*(a+i)) are exactly equivalent;
&a[2] and &(*(a+2)) are both non-conforming. Neither of them is exactly
equivalent to a+2, which is a valid pointer to one past the end of an
array. The other two expressions both contain sub-expressions that
de-reference the pointer, which makes them not strictly conforming.

It has been argued that the de-referencing doesn't actually occur, and
that therefore these expressions shouldn't actually count as violating
that rule. However, a strict reading of the standard doesn't support
that interpretation. There may even be actual conforming implementations
which would unnecessarily physically deference a[i] when they encounter
the expression &a[i].

Larry Jones

unread,
Jan 23, 1998, 3:00:00 AM1/23/98
to

Julian Pardoe wrote:
> As a person who writes &a[i] when I mean the "address of the i'th
> element of a" I am surprised and upset to learn that (in this example)
> &a[2] isn't conforming but a+2 is.

The reason is that a only has two elements -- a[0] and a[1] -- so there
is no a[2] to take the address of. You are allowed to construct a
pointer just past the end of an array, so a+2 is valid.

> In any case I thought a[i] and *(a+i) were defined to be equivalent and
> so would expect &a[i] and &(*(a+i)) to be equivalent.

And they are. &(*(a+i)) is *not* equivalent to a+i, however, if
*(a+i) is invalid.

-Larry Jones

Ha! Wild zontars couldn't drag that information out of me! Do your
worst!
-- Calvin

Dave Hansen

unread,
Jan 23, 1998, 3:00:00 AM1/23/98
to

Posted and emailed.
On Fri, 23 Jan 98 13:28:47 GMT, fr...@genesis.demon.co.uk (Lawrence
Kirby) wrote:

[...]


>This boils down to the definition of "object". Section 3.14 of C90 (and
>section 3.15 of the correct C9X draft) say:
>
>"object: A region of data storage in the execution environment, the contents
> of which can represent values. .... When referenced, an object may be
> interpreted as having a particular type: see 6.2.2.1"

Does the standard define "region?" My copy of the working draft
(n2620.pdf) does not. My dictionary (admittedly not the OED) doesn't
really have a definition that is satisfying in the context of "data
storage." All the definitions, however, imply the concept of
"boundaries" (directly or indirectly).

>
>So type isn't an inherent property of an object (just think of malloc'd

I'd agree that type isn't, but size is. In my mind, a 4-byte integer
(for example) is a different object than an 8-byte (for example)
structure. I _could_ accept that an 8-byte double and an 8-byte
structure _are_ the same object. As you say, type doesn't enter into
it until the object is accessed.

>objects); you can access the same object (or parts of the same object)
>using lvaues of different types. It is better to talk about distinct (i.e.
>non-overlapping) objects rather than different objects. Pointers to distinct

This is the crux of it. Are objects that overlap "distinct" (or
"different") from one another? In the abstract, I would lean toward
"yes." In the face of the standard, I would have to soften that
somewhat (as in the case of the 8-byte double vs. an 8-byte
structure).

>objects (right down to the individual bytes which can be considered as
>separate objects) should compare unequal. You just need to take care about

This is another question. Should pointers to "different" (or
"distinct" objects always compare unequal? Or put another way, should
pointer equivalence imply object equivalence? Here I don't think so.
I have no problem accepting that a pointer to my 4-byte integer might
compare equal with a pointer to my 8-byte structure, even though they
are different objects. In my mind this is the same thing as (given a
declaration like "int a[10];") a vs. &a. The pointers will compare
equal, but they point to different things.

Should pointer difference imply object difference? Absolutely.

Upon reflection, an example from another thread brings this question
to mind. Given

#include <stdio.h>

int main(void)
{
int a, b, *pa = &a, *pb = &b;

printf("%s", (pa==pb? "equal\n": "not equal\n"));
}

Is a conforming implementation allowed to print "equal"? My gut says
"no," but given that a and b are not really used (except to take their
addresses) is the compiler allowed to optimize them away? And if they
are optimized out, do their addresses have to be unequal? I guess I'm
not sure.

Douglas A. Gwyn

unread,
Jan 24, 1998, 3:00:00 AM1/24/98
to

In article <En7GB...@cix.compulink.co.uk>,

jb...@cix.compulink.co.uk ("Julian Pardoe") wrote:
>In article <34C68287...@arl.mil>, gw...@arl.mil (Douglas A. Gwyn)
>wrote:
>> (This is sufficiently strong motivation that there has been an
>> attempt in the C9x draft to legitimatize the expression &a[2],
>> which we believe was not strictly conforming according to C89,
>> although the expression a+2 *is* strictly conforming.)
>As a person who writes &a[i] when I mean the "address of the i'th
>element of a" I am surprised and upset to learn that (in this example)
>&a[2] isn't conforming but a+2 is.
>In any case I thought a[i] and *(a+i) were defined to be equivalent and
>so would expect &a[i] and &(*(a+i)) to be equivalent.

I think you missed that in the specific example, a was declared as
having length 2. Therefore, a[2] is not guaranteed to exist, so one
of the requirements of the operand of the & operator was not satisfied,
namely that the operand be an lvalue that designates an object.

This seems to have been a case of poor specification in the standard,
because there is general agreement that in &a[2] the a[2] refers to a
*potential* object, but a real object doesn't need to be there if the
resulting pointer &a[2] is never dereferenced (but only used in proper
comparisons). We want to "fix" this in C9x, but meanwhile one is
advised to write &a[i] only when a[i] mecessarily exists.


Douglas A. Gwyn

unread,
Jan 24, 1998, 3:00:00 AM1/24/98
to

In article <34c910b1...@192.168.2.34>,

dha...@btree.com (Dave Hansen) wrote:
> #include <stdio.h>
> int main(void)
> {
> int a, b, *pa = &a, *pb = &b;
> printf("%s", (pa==pb? "equal\n": "not equal\n"));
return 0; /* required for strict conformance */

> }
>Is a conforming implementation allowed to print "equal"? My gut says
>"no," but given that a and b are not really used (except to take their
>addresses) is the compiler allowed to optimize them away? And if they
>are optimized out, do their addresses have to be unequal? I guess I'm
>not sure.

I'm 100% sure that if this question were asked in a formal Defect
Report, the committee's response would be essentially:
"No, ``not equal'' must be printed, for any conforming implementation."

Optimization is not allowed to change the meaning of a strictly
conforming program.


Nick Maclaren

unread,
Jan 24, 1998, 3:00:00 AM1/24/98
to

In article <34c910b1...@192.168.2.34>,

Dave Hansen <dha...@btree.com> wrote:
>On Fri, 23 Jan 98 13:28:47 GMT, fr...@genesis.demon.co.uk (Lawrence
>Kirby) wrote:
>
>>This boils down to the definition of "object". Section 3.14 of C90 (and
>>section 3.15 of the correct C9X draft) say:
>>
>>"object: A region of data storage in the execution environment, the contents
>> of which can represent values. .... When referenced, an object may be
>> interpreted as having a particular type: see 6.2.2.1"
>
>Does the standard define "region?" My copy of the working draft
>(n2620.pdf) does not. My dictionary (admittedly not the OED) doesn't
>really have a definition that is satisfying in the context of "data
>storage." All the definitions, however, imply the concept of
>"boundaries" (directly or indirectly).

There is another problem, which is actually the main cause of this
confusion - there are two classes of "object" in the C language.

The first is the unit of guaranteed contiguous data storage, as was
originally allocated, returned from malloc or whatever. Any compatible
pointers to within a single object of this class can be ordered, but
not those between two separate objects of this class.

The second is a defined region of storage, usually associated with a
type, which must be included within an object of the previous class.
As I read the standard, an implementation may not use this class of
object for bounds checking.

This causes havoc for optimisation, and one of the lesser proposals
that I am making is that restrict would allow the compiler to treat
some argument declarations as if they defined objects of the first class
rather than of the second.


Nick Maclaren,
University of Cambridge Computer Laboratory,
New Museums Site, Pembroke Street, Cambridge CB2 3QG, England.
Email: nm...@cam.ac.uk
Tel.: +44 1223 334761 Fax: +44 1223 334679

Julian Pardoe

unread,
Jan 24, 1998, 3:00:00 AM1/24/98
to

In article <34C8E9...@wizard.net>, gul...@wizard.net (James Gulper)
wrote:

> It has been argued that the de-referencing doesn't actually occur, and
> that therefore these expressions shouldn't actually count as violating
> that rule. However, a strict reading of the standard doesn't support
> that interpretation. There may even be actual conforming implementatio

> ns which would unnecessarily physically deference a[i] when they


> encounter the expression &a[i].

Well, then I am surprised. Is this an oversight? Can it be corrected?

As for those implementations, to my mind they are buggy and avoiding
forcing changes on them counts for little.

-- jP --

Bradd W. Szonye

unread,
Jan 24, 1998, 3:00:00 AM1/24/98
to

"Julian Pardoe" wrote in message ...

>In article <34C8E9...@wizard.net>, gul...@wizard.net (James Gulper)
>wrote:
>
>> There may even be actual conforming implementatio
>> ns which would unnecessarily physically deference a[i] when they
>> encounter the expression &a[i].
>
>Well, then I am surprised. Is this an oversight? Can it be corrected?
>
>As for those implementations, to my mind they are buggy and avoiding
>forcing changes on them counts for little.

Why do you consider conforming behavior buggy?

The expressions (a[i]) and (*(a+i)) are both requests from the programmer to
dereference the pointer value (a + i). The expressions &(a[i]) and &(*(a+i))
are both requests from the programmer to dereference a pointer and then take
the address of the resulting lvalue. What's wrong with a compiler generating
code for what the programmer explicitly asks?

Are you saying that a compiler that emits code for "i = 0" when i is never
subsequently referenced is also buggy?

You're confusing bugs with quality-of-implementation. Just because an
optimization is trivial does not mean that a compiler must perform the
optimization to be conforming. Nor does it make it buggy. In the case of
&a[i], you could even say that it's a higher quality of implementation than
the optimized version, because it attempts to exert undefined behavior.
Which is useful for debugging.
---
Bradd W. Szonye
bra...@concentric.net
http://www.concentric.net/~Bradds

Clive D.W. Feather

unread,
Jan 24, 1998, 3:00:00 AM1/24/98
to

In article <En7GB...@cix.compulink.co.uk>, Julian Pardoe
<jb...@cix.compulink.co.uk> writes

>> (This is sufficiently strong motivation that there has been an
>> attempt in the C9x draft to legitimatize the expression &a[2],
>> which we believe was not strictly conforming according to C89,
>> although the expression a+2 *is* strictly conforming.)
>As a person who writes &a[i] when I mean the "address of the i'th
>element of a" I am surprised and upset to learn that (in this example)
>&a[2] isn't conforming but a+2 is.

Remember that a+2 is a pointer to one beyond the end of an array, not to
an object. So &a[2] is &*(a+2) which theoretically dereferences this
pointer.

Another case is:

char *a = NULL;
&*a;

We've added words in C9X that makes &* a no-op, in both direct and the
&a[i] cases. The result is not an lvalue.

Clive D.W. Feather

unread,
Jan 24, 1998, 3:00:00 AM1/24/98
to

In article <34c910b1...@192.168.2.34>, Dave Hansen
<dha...@btree.com> writes

>Upon reflection, an example from another thread brings this question
>to mind. Given
>
> #include <stdio.h>
>
> int main(void)
> {
> int a, b, *pa = &a, *pb = &b;
>
> printf("%s", (pa==pb? "equal\n": "not equal\n"));
> }
>
>Is a conforming implementation allowed to print "equal"?

No. Asked and answered in a DR.

>given that a and b are not really used (except to take their
>addresses) is the compiler allowed to optimize them away? And if they
>are optimized out, do their addresses have to be unequal?

Yes, they still have to be unequal; the DR said so.

C89 says something like "the object exists for the duration of the
block", and C9X adds "and has a distinct address".

Geoffrey KEATING

unread,
Jan 25, 1998, 3:00:00 AM1/25/98
to

In article <34C8E9...@wizard.net>, gul...@wizard.net (James Gulper)
wrote:

> There may even be actual conforming implementatio
> ns which would unnecessarily physically deference a[i] when they
> encounter the expression &a[i].

... in fact, if *a is volatile, I think the standard may require
this.

--
Geoff Keating <Geoff....@anu.edu.au>

Douglas A. Gwyn

unread,
Jan 25, 1998, 3:00:00 AM1/25/98
to

In article <EnAz9...@cix.compulink.co.uk>,

jb...@cix.compulink.co.uk ("Julian Pardoe") wrote:
>As for those implementations, to my mind they are buggy and avoiding
>forcing changes on them counts for little.

They're not buggy if they're simply following the
abstract machine semantics literally rather than
performing "obvious" short cuts.


Lawrence Kirby

unread,
Jan 25, 1998, 3:00:00 AM1/25/98
to

In article <6ae0j2$l...@examiner.concentric.net>

bra...@concentric.net "Bradd W. Szonye" writes:

>"Julian Pardoe" wrote in message ...

>>In article <34C8E9...@wizard.net>, gul...@wizard.net (James Gulper)
>>wrote:
>>
>>> There may even be actual conforming implementatio
>>> ns which would unnecessarily physically deference a[i] when they
>>> encounter the expression &a[i].
>>

>>Well, then I am surprised. Is this an oversight? Can it be corrected?
>>

>>As for those implementations, to my mind they are buggy and avoiding
>>forcing changes on them counts for little.
>

>Why do you consider conforming behavior buggy?
>
>The expressions (a[i]) and (*(a+i)) are both requests from the programmer to
>dereference the pointer value (a + i). The expressions &(a[i]) and &(*(a+i))
>are both requests from the programmer to dereference a pointer and then take
>the address of the resulting lvalue. What's wrong with a compiler generating
>code for what the programmer explicitly asks?

The real sticking point is that if there is no object then you can't
create an lvalue. Creating an lvalue doesn't imply that a value is accessed.
In fact 6.2.2.1 makes it fairly clear that in this case it isn't (the lvalue
is not converted to a value here). There's nothing in the current standard
that indicates that &*(a+i) should access the value of *(a+i). In fact if
a is a pointer to volatile type then it would be an error in general
to access the value.

Lawrence Kirby

unread,
Jan 25, 1998, 3:00:00 AM1/25/98
to

In article <34c910b1...@192.168.2.34>
dha...@btree.com "Dave Hansen" writes:

>Posted and emailed.


>On Fri, 23 Jan 98 13:28:47 GMT, fr...@genesis.demon.co.uk (Lawrence
>Kirby) wrote:
>

>[...]


>>This boils down to the definition of "object". Section 3.14 of C90 (and
>>section 3.15 of the correct C9X draft) say:
>>
>>"object: A region of data storage in the execution environment, the contents
>> of which can represent values. .... When referenced, an object may be
>> interpreted as having a particular type: see 6.2.2.1"
>
>Does the standard define "region?" My copy of the working draft
>(n2620.pdf) does not. My dictionary (admittedly not the OED) doesn't
>really have a definition that is satisfying in the context of "data
>storage." All the definitions, however, imply the concept of
>"boundaries" (directly or indirectly).

The standard does define region. I think you can just take it to mean
a single bounded entity. The next sentence tells us what that entity
consists of.

>>So type isn't an inherent property of an object (just think of malloc'd
>
>I'd agree that type isn't, but size is. In my mind, a 4-byte integer
>(for example) is a different object than an 8-byte (for example)
>structure.

True, an 8 byte object is different from a 4 byte object but they may not
be distinct. For example you might take 4 bytes of the 8 byte object and
consider them as a 4 byte object, to consider each of the 8 bytes as a
separate object.

> I _could_ accept that an 8-byte double and an 8-byte
>structure _are_ the same object. As you say, type doesn't enter into
>it until the object is accessed.

Right, two objects are the same if they consist of the same sequence of
contiguous bytes. An object may be interpreted in different ways by
changing the type of lvalue it is accessed through.

>>objects); you can access the same object (or parts of the same object)
>>using lvaues of different types. It is better to talk about distinct (i.e.
>>non-overlapping) objects rather than different objects. Pointers to distinct
>
>This is the crux of it. Are objects that overlap "distinct" (or
>"different") from one another? In the abstract, I would lean toward
>"yes." In the face of the standard, I would have to soften that
>somewhat (as in the case of the 8-byte double vs. an 8-byte
>structure).

I would say they are not distinct. But that is somewhat circular since
my definition of "are distinct" in this context is "don't overlap".

>>objects (right down to the individual bytes which can be considered as
>>separate objects) should compare unequal. You just need to take care about
>
>This is another question. Should pointers to "different" (or
>"distinct" objects always compare unequal?

Different objects, not necessarily. Distinct objects, yes. Firstly you need
to bring pointer to a common type to compare them and for pointers to objects
the only safe types for that are pointers to a character type and to void
(which all have the same representation). Assuming that converting to a
pointer to a character type will result in a pointer that points to a byte
of the object (*) then the bytes pointed to by the two resulting pointers
will be distinct hence the pointers will compare unequal.

* - although universally assumed the current and draft standards don't
explicitly guarantee this. This has been flagged as a defect through
UK public comments. The result should be defined as a pointer to the
lowest addressed byte of the object.

> Or put another way, should
>pointer equivalence imply object equivalence? Here I don't think so.
>I have no problem accepting that a pointer to my 4-byte integer might
>compare equal with a pointer to my 8-byte structure, even though they
>are different objects. In my mind this is the same thing as (given a
>declaration like "int a[10];") a vs. &a. The pointers will compare
>equal, but they point to different things.

Right, noting that pointers need to be converted to a common type to be
compared the precise meaning depends on what the common type is. For a
pointer to a character type or to void equality means that the two objects
start at the same byte address.

>Should pointer difference imply object difference? Absolutely.

It means that they start at a different byte address which makes the
objects different but not necessarily distinct.

>Upon reflection, an example from another thread brings this question
>to mind. Given
>
> #include <stdio.h>
>
> int main(void)
> {
> int a, b, *pa = &a, *pb = &b;
>
> printf("%s", (pa==pb? "equal\n": "not equal\n"));
> }
>

>Is a conforming implementation allowed to print "equal"? My gut says

>"no," but given that a and b are not really used (except to take their


>addresses) is the compiler allowed to optimize them away? And if they

>are optimized out, do their addresses have to be unequal? I guess I'm
>not sure.

5.1.2.3:

"The semantic descriptions in this International Standard describe the
behaviour of an abstract machine in which issues of optimisation are
irrelevant."

The point is that optimisation has no part in determining the bahaviour
defined by the source code of a program. In the program above the definition
of a and b as distinct objects is a fact and the program has well-defined
semantics based on that. All forms of translation must respect those
semantics - it doesn't matter how the program output is achieved as long
as the output is correct (which also means no extra visible side-effects
to the ones defined by the program).

Scott Mayo

unread,
Jan 25, 1998, 3:00:00 AM1/25/98
to

In comp.std.c, fr...@genesis.demon.co.uk (Lawrence Kirby) wrote:

<I would say they are not distinct. But that is somewhat circular since
<my definition of "are distinct" in this context is "don't overlap".

I'm still a little lost. Let me explain the cases I am explicitly
worried about. I have a kind of object (say, a 'struct Thing') and I expect
to create a number of them, via malloc or on the stack or statically.
And I create pointers to each, and carry the pointers around.

1. Are all these pointers absolutely guaranteed to be unequal to each
other? Consider the case of two static, const instances of the struct, initialised
identically. Is the compiler allowed to make them the same object? I
assume no, but I've been a little scared by things involving string literals.

2. Even more pressing, When I deal in these pointers, I need *more than one*
special value for the pointer that doesn't really point to one of the
objects, but implies something different. Obviously, NULL is a good choice
for one of these "special values", but I need two or more. These special
values won't be dereferenced, they will only be checked for equality
with the special value constant.

One (ancient and unportable) hack is

#define SPECIAL_VALUE_1 (struct Thing*)1
#define SPECIAL_VALUE_2 (struct Thing*)2

struct Thing *p;
...
if (p == SPECIAL_VALUE_1) // it's a case of foo!
...
if (p == SPECIAL_VALUE_2) // it's a case of bar!

but I know that's unportable and evil. Those aren't "real" pointers.
Instead, I'd like to try:

static unsigned char fakething1;
static unsigned char fakething2;

#define SPECIAL_VALUE_1 (struct Thing*)&fakething1
#define SPECIAL_VALUE_2 (struct Thing*)&fakething2

and when I do my comparisons against p, I'd like to be sure that there
is absolutely no way that (p == SPECIAL_VALUE_1) can compare true
for any actual instance of struct Thing - and of course that
(SPECIAL_VALUE_1 != SPECIAL_VALUE_2).

I can probably make my case better by making fakething1 and 2 be instances
of struct Thing, but assume that's awkward of size limitations. :)


Dennis Yelle

unread,
Jan 25, 1998, 3:00:00 AM1/25/98
to

In article <GEOFFK.98J...@discus.anu.edu.au> geo...@discus.anu.edu.au (Geoffrey KEATING) writes:
>In article <34C8E9...@wizard.net>, gul...@wizard.net (James Gulper)
>wrote:
>
>> There may even be actual conforming implementatio
>> ns which would unnecessarily physically deference a[i] when they
>> encounter the expression &a[i].
>
>... in fact, if *a is volatile, I think the standard may require
>this.

If so, then (obviously ?) there is a bug in the standard.

If you can support your thought, maybe we can get this fixed.

Dennis Yelle

--
den...@netcom.com (Dennis Yelle)
"You must do the thing you think you cannot do." -- Eleanor Roosevelt

Julian Pardoe

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

In article <GEOFFK.98J...@discus.ana.edu.au>,
geo...@discus.anu.edu.au (Geoffrey KEATING) wrote:

> In article <34C8E9...@wizard.net>, gul...@wizard.net (James Gulper
> )
> wrote:
>
> > There may even be actual conforming implementatio
> > ns which would unnecessarily physically deference a[i] when they
> > encounter the expression &a[i].
>
> ... in fact, if *a is volatile, I think the standard may require
> this.

Does it? -- can someone replace "think" by "know"? I could believe it
either way.

But why the distinction between &a[i] and &(*(a+i))? That's what's
bugging me!

-- jP --

Julian Pardoe

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

In article <6ae0j2$l...@examiner.concentric.net>, bra...@concentric.net
(Bradd W. Szonye) wrote:

> "Julian Pardoe" wrote in message ...

> >In article <34C8E9...@wizard.net>, gul...@wizard.net (James Gulpe
> r)
> >wrote:
> >
> >> There may even be actual conforming implementatio
> >> ns which would unnecessarily physically deference a[i] when they
> >> encounter the expression &a[i].
> >

> >Well, then I am surprised. Is this an oversight? Can it be correcte
> d?
> >
> >As for those implementations, to my mind they are buggy and avoiding
> >forcing changes on them counts for little.
>
> Why do you consider conforming behavior buggy?

I think I am being drawn into a discussion different to the one I
started. I can certainly conceive of architectures where the normal way
of evaluating &a[i] would involve validation of the address, so I can
see why in general one-past-the-end pointers could cause problems.

What I can't see is why &a[n] should be treated differently from
&(*(a+n))! (n is the number of elements in the array.)

> The expressions (a[i]) and (*(a+i)) are both requests from the program
> mer to dereference the pointer value (a + i). The expressions &(a[i])
> and &(*(a+i)) are both requests from the programmer to dereference a

> pointer and the n take the address of the resulting lvalue.

Well, I can conceive of an architectures where values were
(lvalue,rvalue) pairs and where this explanation of the meaning of &a[i]
would be appropriate but I can think of other explanations that are
simpler and don't involved talk of "dereferencing". (Of course, it
depends what you mean by "dereferencing": I take it to mean an
lvalue->rvalue operation.)

> What's wrong with a compiler generating
> code for what the programmer explicitly asks?

When I write p = &a[i] I don't consider myself asking for
temp = a[i]; p = &a[i];

Still, I think you mean something different to what I do when you say
"dereference". If you count forming the address as "dereferencing" (I
don't) then I agree with you -- see my first comments.

And this is all irrelevant to my basic point.

> You're confusing bugs with quality-of-implementation.

Well, yes and no. You misunderstood what I meant by "buggy". As I
understood it one of the goals of the Standard was not to cause to much
disruption to existing implementations, to protect them as it were.

Now, we are told that undefined behaviour could involve gratuitously
reformatting one's hard drive. So, it your sense an implementation that
did this would not be buggy. If the committee wanted to change the
standard so as to outlaw the reformatting of hard drives in this case, I
wouldn't consider the protection of implementations that did so as an
important factor in the debate. They would, in my sense, be "buggy"
implementations: gratuitously reformatting the hard drive may be
conforming but it is also, in a sense, a bug and so is behaviour that is
not worthy of protection.

I would consider a compiler that treated &a[n] differently to &(*(a+n))
as buggy in this sense.

The original poster did say "unnecessarily". As you say, a compiler is
technically free to do all sorts of "unnecessary" things and still
remain conforming. I would nevertheless consider such a compiler as not
worth damaging the standard for, as "unworthy of protection".

-- jP --

Julian Pardoe

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

In article <jTUxQxAi...@romana.davros.org>,
cl...@on-the-train.demon.co.uk (Clive D.W. Feather) wrote:

> We've added words in C9X that makes &* a no-op, in both direct and the
> &a[i] cases. The result is not an lvalue.

Good! That is what I wanted to hear! (I seem to have been dragged into
all sorts of irrelevant discussions.)

Tough for all the implementors of those "buggy" (in _my_ sense)
compilers.

-- jP --

Lawrence Kirby

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

In article <2618c.sm...@ziplink.net> sm...@ziplink.net "Scott Mayo" writes:

>In comp.std.c, fr...@genesis.demon.co.uk (Lawrence Kirby) wrote:
>

><I would say they are not distinct. But that is somewhat circular since
><my definition of "are distinct" in this context is "don't overlap".
>

>I'm still a little lost. Let me explain the cases I am explicitly
>worried about. I have a kind of object (say, a 'struct Thing') and I expect
>to create a number of them, via malloc or on the stack or statically.
>And I create pointers to each, and carry the pointers around.
>
>1. Are all these pointers absolutely guaranteed to be unequal to each
>other? Consider the case of two static, const instances of the struct,
> initialised
>identically. Is the compiler allowed to make them the same object?

The answer is no, unless the standard gives special license for that to
happen.

>I
>assume no, but I've been a little scared by things involving string literals.

C89 gives special license for string literals to be folded (i.e. the
objects designated by two string literals may overlap if, of course their
contents are compatible). String literals may not overlap with an object
created in any other way.

The C9X draft extends this to compound literals with const qualified types.
So any combination of string and const qualified compound literals may
overlap (assuming compatible data). However objects created in any other way
may not overlap with these or anything else. So objects created by
variable definitions, malloc/calloc/realloc and objects that are part of the
runtime environment (e.g. objects referenced from main's argv, errno, return
values from library functions such as getenv() or localtime()) are all
distinct.

You'll have to do that to be portable. There's no guarantee that
fakething1 and fakething2 have alignment appropriate for anything other
than a character. Therefore the behaviour of the cast to (struct Thing *)
is undefined (although that area of the standard has always been vague,
one thing for certain though is that the result isn't specified).

James Kuyper

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

Julian Pardoe wrote:
...

> What I can't see is why &a[n] should be treated differently from
> &(*(a+n))! (n is the number of elements in the array.)

&a[i], &(*(a+i)), and a+i all equal for i<n. However, for i==n, the
first two expressions explicitly dereference a pointer that points one
past the end of the array they were derived from, permitting undefined
behavior; the third expression does not, so it is safe. &a[n] and
&(*(a+n)) are NOT being treated differently.

...


> When I write p = &a[i] I don't consider myself asking for
> temp = a[i]; p = &a[i];

What happens when you dereference a pointer cannot be written in 'C';
it's at a lower level than that. It also cannot be written in
standardese, because the standard is deliberately vague enough to allow
many different implementations. However, one previously allowed type of
implementation would perform actions preparatory to reading or writing
whenever the expression '*(a+i)' occurs; preparations which might fail
if the address can neither be read to nor written to. This was allowed
behavior, even when *(a+i) occured in the context of &(*(a+i)), in which
case those preparations were unnecessary. Nothing in the standard
required the implementation to be smart enough to skip those
preparations, until the recent wording change.

> Still, I think you mean something different to what I do when you say
> "dereference". If you count forming the address as "dereferencing" (I
> don't) then I agree with you -- see my first comments.

Applying the '*' operator to a pointer is dereferencing the pointer;
even if it occurs in the context of '&(*p)'. Before the recently revised
wording was approved, this permitted undefined behavior in the case of
&a[n] if 'n' is the length of the array.

Dennis Yelle

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to
[...]

>>Instead, I'd like to try:
>>
>>static unsigned char fakething1;
>>static unsigned char fakething2;
>>
>>#define SPECIAL_VALUE_1 (struct Thing*)&fakething1
>>#define SPECIAL_VALUE_2 (struct Thing*)&fakething2
>>
>>and when I do my comparisons against p, I'd like to be sure that there
>>is absolutely no way that (p == SPECIAL_VALUE_1) can compare true
>>for any actual instance of struct Thing - and of course that
>>(SPECIAL_VALUE_1 != SPECIAL_VALUE_2).
>>
>>I can probably make my case better by making fakething1 and 2 be instances
>>of struct Thing, but assume that's awkward of size limitations. :)
>
>You'll have to do that to be portable. There's no guarantee that
>fakething1 and fakething2 have alignment appropriate for anything other
>than a character. Therefore the behaviour of the cast to (struct Thing *)
>is undefined (although that area of the standard has always been vague,
>one thing for certain though is that the result isn't specified).

Well, we also have the "all struct pointers smell the same," rule.
So, this should work properly:

struct fake_struct { char fake; };

static struct fake_struct fakething1;
static struct fake_struct fakething2;

#define SPECIAL_VALUE_1 ((struct Thing*)&fakething1)
#define SPECIAL_VALUE_2 ((struct Thing*)&fakething2)

Scott Mayo

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

In comp.std.c, fr...@genesis.demon.co.uk (Lawrence Kirby) wrote:
<In article <2618c.sm...@ziplink.net> sm...@ziplink.net "Scott Mayo" writes:

<>static unsigned char fakething1;
<>static unsigned char fakething2;
<>
<>#define SPECIAL_VALUE_1 (struct Thing*)&fakething1
<>#define SPECIAL_VALUE_2 (struct Thing*)&fakething2

<There's no guarantee that


<fakething1 and fakething2 have alignment appropriate for anything other
<than a character. Therefore the behaviour of the cast to (struct Thing *)
<is undefined (although that area of the standard has always been vague,
<one thing for certain though is that the result isn't specified).

Hm. This makes sense, but it raises a question - could the standard provide
a typedef to something, anything, that has maximally difficult alignment
restrictions for that implementation? Such that, a pointer to it is automatically
suitable, alignment-wise, for any object? Something like:

typedef long alignment_t;

I'm 98% certain that malloc(1) provides such a pointer, when it doesn't
provide NULL, but not 100% - it might look at the argument and decide
that something of size 1 could be stored off-alignment. (No harm done;
if it gets realloc'd bigger, it can move the object.) But of couse I
don't want to use malloc() for this purpose; it might return NULL.

Norman Diamond

unread,
Jan 27, 1998, 3:00:00 AM1/27/98
to

In article <EnEC7...@cix.compulink.co.uk>, jb...@cix.compulink.co.uk ("Julian Pardoe") writes:
>In article <GEOFFK.98J...@discus.ana.edu.au>,
>geo...@discus.anu.edu.au (Geoffrey KEATING) wrote:
>>In article <34C8E9...@wizard.net>, gul...@wizard.net (James Gulper)
>>wrote:
>>>There may even be actual conforming implementations which would

>>>unnecessarily physically deference a[i] when they encounter the
>>>expression &a[i].

>>... in fact, if *a is volatile, I think the standard may require this.

>Does it? -- can someone replace "think" by "know"? I could believe it
>either way.

I don't believe anyone can know for sure, because it's sort of vacuumed
(i.e. made inherently vacuous) by the words "What constitutes access to
an object that has volatile-qualified type is implementation-defined."

>But why the distinction between &a[i] and &(*(a+i))? That's what's
>bugging me!

If there is a distinction there, it bugs me too. Last time I noticed a
proposal, &a[i] and &*(a+i) were both being given new definitions. Didn't
look for it in the CD though.

In C89, there's an obvious difference between &a[i] and a+i.

--
<< If this were the company's opinion, I would not be allowed to post it. >>
"I paid money for this car, I pay taxes for vehicle registration and a driver's
license, so I can drive in any lane I want, and no innocent victim gets to call
the cops just 'cause the lane's not goin' the same direction as me" - J Spammer

Lawrence Kirby

unread,
Jan 27, 1998, 3:00:00 AM1/27/98
to

In article <dennisEn...@netcom.com> den...@netcom.com "Dennis Yelle" writes:

>>In article <2618c.sm...@ziplink.net> sm...@ziplink.net "Scott Mayo"
> writes:

>[...]
>>>Instead, I'd like to try:
>>>

>>>static unsigned char fakething1;
>>>static unsigned char fakething2;
>>>
>>>#define SPECIAL_VALUE_1 (struct Thing*)&fakething1
>>>#define SPECIAL_VALUE_2 (struct Thing*)&fakething2
>>>

>>>and when I do my comparisons against p, I'd like to be sure that there
>>>is absolutely no way that (p == SPECIAL_VALUE_1) can compare true
>>>for any actual instance of struct Thing - and of course that
>>>(SPECIAL_VALUE_1 != SPECIAL_VALUE_2).
>>>
>>>I can probably make my case better by making fakething1 and 2 be instances
>>>of struct Thing, but assume that's awkward of size limitations. :)
>>

>>You'll have to do that to be portable. There's no guarantee that


>>fakething1 and fakething2 have alignment appropriate for anything other
>>than a character. Therefore the behaviour of the cast to (struct Thing *)
>>is undefined (although that area of the standard has always been vague,
>>one thing for certain though is that the result isn't specified).
>

>Well, we also have the "all struct pointers smell the same," rule.

Lets be clear here. What the C9X draft 6.1.2.5p26 says is:

"All pointers to structure types shall have the same representation and
alignment requirements."

You can almost deduce this in C89 from the fact that there are compatibility
requirements between incomplete and object structure types.

>So, this should work properly:
>
> struct fake_struct { char fake; };
>
> static struct fake_struct fakething1;
> static struct fake_struct fakething2;
>
> #define SPECIAL_VALUE_1 ((struct Thing*)&fakething1)
> #define SPECIAL_VALUE_2 ((struct Thing*)&fakething2)

Well, you might be able to do the conversion but that doesn't mean you
will get sensible results from dereferencing the pointer. One thing you
should be able to do is convert a pointer to a struct to a different
pointer to struct type and back again and get back your original pointer.
That's useful for hiding information behind incomplete structure types.

Dennis Yelle

unread,
Jan 27, 1998, 3:00:00 AM1/27/98
to

Well, the original requirement was not that the SPECIAL_VALUE pointers be
dereferencable. The only original requirement was that "real" pointers
would never compare equal to any of the SPECIAL_VALUEs when checked
with the == operator.

I claim that the code with the fake_struct containing a single
character satisfies this requirement in a portable way. Do you disagree?

Julian Pardoe

unread,
Jan 27, 1998, 3:00:00 AM1/27/98
to

In article <6ajti8$ge9$1...@nntpd.lkg.dec.com>, dia...@tbj.dec.com (Norman
Diamond) wrote:

> In C89, there's an obvious difference between &a[i] and a+i.

Is there? -- apart, that is, from the one we're both unhappy about.
Please elucidate -- by mail if you feel that's more appropriate.

-- jP --


Julian Pardoe

unread,
Jan 28, 1998, 3:00:00 AM1/28/98
to

In article <34CD1A...@wizard.net>, kuy...@wizard.net (James Kuyper)
wrote:

> &a[i], &(*(a+i)), and a+i all equal for i<n. However, for i==n, the
> first two expressions explicitly dereference a pointer that points one
> past the end of the array they were derived from, permitting undefined
> behavior; the third expression does not, so it is safe. &a[n] and
> &(*(a+n)) are NOT being treated differently.

I am surprised! Is this true? Perhaps someone with suitable "language
lawyer" knowledge of the C89 standard would care to comment. (I have
"language lawyer" tendencies but I am handicapped by not having a copy
of the standard in front of me.)

I would expect the statement "the first two expressions explicitly
dereference a pointer that points one past the end of the array" to be
in error but again I can't be sure.

Clive's article <jTUxQxAi...@romana.davros.org> suggests to me that
there was an issue but that it has been resolved in C9X.

-- jP --

Clive D.W. Feather

unread,
Feb 2, 1998, 3:00:00 AM2/2/98
to

In article <885915...@genesis.demon.co.uk>, Lawrence Kirby
<fr...@genesis.demon.co.uk> writes

>>Well, we also have the "all struct pointers smell the same," rule.
>Lets be clear here. What the C9X draft 6.1.2.5p26 says is:
>"All pointers to structure types shall have the same representation and
> alignment requirements."

Right. Added since C89.

>You can almost deduce this in C89 from the fact that there are compatibility
>requirements between incomplete and object structure types.

Part of the deduction relied on the "common initial subsequence" rule.
This rule has been revised (to require the two structures within the
union construction to be visible), and this breaks the logic.

Clive D.W. Feather

unread,
Feb 2, 1998, 3:00:00 AM2/2/98
to

In article <EnEC7...@cix.compulink.co.uk>, Julian Pardoe
<jb...@cix.compulink.co.uk> writes

>But why the distinction between &a[i] and &(*(a+i))? That's what's
>bugging me!

Huh ?

6.3.2.1p2 (unchanged from C89, I think):

| The definition of the subscript operator [] is that E1[E2] is
| identical to (*(E1+(E2))).

That's it. No difference.

Clive D.W. Feather

unread,
Feb 2, 1998, 3:00:00 AM2/2/98
to

In article <2629a.sm...@ziplink.net>, Scott Mayo
<sm...@ziplink.net> writes

>Hm. This makes sense, but it raises a question - could the standard provide
>a typedef to something, anything, that has maximally difficult alignment
>restrictions for that implementation? Such that, a pointer to it is
>automatically
>suitable, alignment-wise, for any object? Something like:
>
>typedef long alignment_t;

There might not be such a type. However, it would be sensible to provide
a symbol __ALIGNMENT__ that can be used with malloced structure to
retain alignment.

>I'm 98% certain that malloc(1) provides such a pointer, when it doesn't
>provide NULL, but not 100% - it might look at the argument and decide
>that something of size 1 could be stored off-alignment.

There was a DR about this, and WG14 said that the alignment requirement
holds no matter what size is asked for. So it *is* 100%.

Clive D.W. Feather

unread,
Feb 2, 1998, 3:00:00 AM2/2/98
to

In article <EnGw0...@cix.compulink.co.uk>, Julian Pardoe
<jb...@cix.compulink.co.uk> writes

>> &a[i], &(*(a+i)), and a+i all equal for i<n.

Well, for 0 <= i < n.

>I would expect the statement "the first two expressions explicitly
>dereference a pointer that points one past the end of the array" to be
>in error but again I can't be sure.
>Clive's article <jTUxQxAi...@romana.davros.org> suggests to me that
>there was an issue but that it has been resolved in C9X.

The wording of C89 didn't make it totally clear whether or not the
deference could happen. We've clarified that in C9X, such that all three
of the above expressions are equivalent in all contexts.

Henning Makholm

unread,
Feb 2, 1998, 3:00:00 AM2/2/98
to

"Clive D.W. Feather" <cl...@on-the-train.demon.co.uk> writes:

> >I'm 98% certain that malloc(1) provides such a pointer, when it doesn't
> >provide NULL, but not 100% - it might look at the argument and decide
> >that something of size 1 could be stored off-alignment.
>
> There was a DR about this, and WG14 said that the alignment requirement
> holds no matter what size is asked for. So it *is* 100%.

Can a conforming program tell?

--
Henning Makholm
http://www.diku.dk/students/makholm

Clive D.W. Feather

unread,
Feb 2, 1998, 3:00:00 AM2/2/98
to

In article <yahoh0q...@ivalde.diku.dk>, Henning Makholm
<mak...@ivalde.diku.dk> writes

>> There was a DR about this, and WG14 said that the alignment requirement
>> holds no matter what size is asked for. So it *is* 100%.
>Can a conforming program tell?

A conforming implementation can, yes.

A strictly-conforming one ? I don't know offhand. Probably not. But
that's a poor basis for making any decisions. For example, converting a
pointer to an integer is not strictly conforming, but on the vast
majority of implementations the resulting number is useful (for example,
it will be a multiple of the required alignment).

Henning Makholm

unread,
Feb 3, 1998, 3:00:00 AM2/3/98
to

"Clive D.W. Feather" <cl...@on-the-train.demon.co.uk> writes:

> In article <yahoh0q...@ivalde.diku.dk>, Henning Makholm
> <mak...@ivalde.diku.dk> writes

> >> There was a DR about this, and WG14 said that the alignment requirement
> >> holds no matter what size is asked for. So it *is* 100%.
> >Can a conforming program tell?

> A strictly-conforming one ? I don't know offhand. Probably not. But


> that's a poor basis for making any decisions.

What I meant was something along the lines of: does the standard
prevent an implementation from declaring that a pointer to the last
byte of physical memory *is* correctly "aligned" for anything but
that trying to *use* it for anything will format the hard disk - and
return such a pointer from malloc(1)?

I just found out that I think a strictly conforming program *can* tell:

int main(void) {
void *p = malloc(1) ;
return (p == (void*)(int*)p) ? EXIT_SUCCESS : EXIT_FAILURE ;
}

The alignment requirement seems to be the only thing that guarantees
that the conversion to int* does not loose information.

However, I still think that malloc(1) on an implementation where all
pointers have the same representation may still return a pointer that
is not "aligned" in the everyday, non-standardese meaning of the term.
Because it is undefined anyway what happens when one tries to use the
pointer to access an object bigger than the size I asked malloc() for.

Clive D.W. Feather

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to

In article <yahiuqx...@berling.diku.dk>, Henning Makholm
<mak...@berling.diku.dk> writes

>I just found out that I think a strictly conforming program *can* tell:
>
> int main(void) {
> void *p = malloc(1) ;
> return (p == (void*)(int*)p) ? EXIT_SUCCESS : EXIT_FAILURE ;
> }
>
>The alignment requirement seems to be the only thing that guarantees
>that the conversion to int* does not loose information.

The double cast *might* change a misaligned pointer, but it might not.
So a conforming implementation cannot cause that program to generate
EXIT_FAILURE, but a non-conforming one might still return EXIT_SUCCESS.

Henning Makholm

unread,
Feb 5, 1998, 3:00:00 AM2/5/98
to

"Clive D.W. Feather" <cl...@on-the-train.demon.co.uk> writes:

> The double cast *might* change a misaligned pointer, but it might not.
> So a conforming implementation cannot cause that program to generate
> EXIT_FAILURE, but a non-conforming one might still return EXIT_SUCCESS.

Of course, a non-conforming implementation can do anyting.

0 new messages