Topic: Comparison of pointers cast to void *
Author: Yechezkel Mett <ymett.on.usenet@gmail.com>
Date: Wed, 7 Nov 2007 16:08:25 CST Raw View
On Oct 30, 12:22 am, Alan McKenney <alan_mckenn...@yahoo.com> wrote:
> The situation I envisioned where this could come up is
> a word-addressed machine where one word contains
> multiple characters (let's say 8.)
>
> In that case, a sensible way of representing pointers to char
> types would be to have the index within the word in the bottom three
> bits and the pointer to the word in the higher-order bits.
>
> Pointers to other built-in types and to objects would be word
> pointers.
>
> Next, it would make sense to have cast to "void *" just copy the
> bits in the pointer -- why do extra work?
>
> But if you do it this way, then you could have a pointer to char
> and a pointer to a double be the same, if the double's word address
> was 8 times the char's word address.
Isn't it legal to cast the void* to an unsigned char* and memcpy the
bytes (assuming the type is memcpy-able) ? I don't see how that could
be made to work under your scenario. Maybe if the implementation
retained extra pointer type information which didn't participate in
comparisons.
Yechezkel Mett
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: James Kanze <james.kanze@gmail.com>
Date: Wed, 7 Nov 2007 16:16:48 CST Raw View
On Oct 30, 4:13 am, Alan McKenney <alan_mckenn...@yahoo.com> wrote:
> On Oct 29, 6:23 pm, AlbertoBarb...@libero.it (Alberto Ganesh Barbati)
> wrote:
> > Alan McKenney ha scritto:
> > > if you have pointers to two different objects and you cast them
> > > to void *, is it legal for them to compare equal?
> <snip>
> > 4.10/2 says that "The result of converting a "pointer to cv T" to a
> > "pointer to cv void" points to the start of the storage location where
> > the object of type T resides, as if the object is a most derived object
> > (1.8) of type T (that is, not a base class subobject)."
> But what exactly does "points to" mean?
> Perhaps I'm dense, but I can only understand
> "points to" to mean: what you get when you
> dereference the pointer.
> And since you can't dereference a void *, this
> means casting it back to a pointer to a type.
> In particular, as far as I know from postings
> on c.l.c++.m and c.s.c++, this means casting it
> back to the type that it was cast from, since
> that's the only legal cast for a void *.
You can also cast it to unsigned char*, and look at the raw
memory.
> So, you should be able to have the same void *
> bit pattern "point to" two different objects,
> depending upon what type you consider it to
> be. In the implementation I describe, that's
> what actually happens with the non-void pointers:
> the same bit pattern can address two different
> parts of memory, depending upon what type
> it is assumed to have.
The implementation you described isn't legal, since it causes
void* to loose information. You must be able to cast any
pointer to void*, and back again, without loss of information;
the pointer from the round trip must compare equal to the
original pointer, and designate the same object.
If two void* actually point to two different objects, then it is
guaranteed that they compare inequal. If a void* points to one
beyond the last element of an array, however, it may compare
equal to a void* which points to some other object (not the
array, nor any element in the array).
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Alan McKenney <alan_mckenney1@yahoo.com>
Date: Thu, 8 Nov 2007 10:59:39 CST Raw View
On Nov 7, 5:16 pm, James Kanze <james.ka...@gmail.com> wrote:
> On Oct 30, 4:13 am, Alan McKenney <alan_mckenn...@yahoo.com> wrote:
>
>
>
> > On Oct 29, 6:23 pm, AlbertoBarb...@libero.it (Alberto Ganesh Barbati)
> > wrote:
> > > Alan McKenney ha scritto:
> > > > if you have pointers to two different objects and you cast them
> > > > to void *, is it legal for them to compare equal?
> > <snip>
> > > 4.10/2 says that "The result of converting a "pointer to cv T" to a
> > > "pointer to cv void" points to the start of the storage location where
> > > the object of type T resides, as if the object is a most derived object
> > > (1.8) of type T (that is, not a base class subobject)."
> > But what exactly does "points to" mean?
> > Perhaps I'm dense, but I can only understand
> > "points to" to mean: what you get when you
> > dereference the pointer.
> > And since you can't dereference a void *, this
> > means casting it back to a pointer to a type.
> > In particular, as far as I know from postings
> > on c.l.c++.m and c.s.c++, this means casting it
> > back to the type that it was cast from, since
> > that's the only legal cast for a void *.
>
> You can also cast it to unsigned char*, and look at the raw
> memory.
In other words, the standard specifically requires that
void * be equivalent ("isomorphic") to unsigned char *
Furthermore, since you speak of "looking at the raw memory"
through this pointer, it sounds like even if the hardware is not
byte-addressable (or is even more exotic), the implementation
must make it look like everything is stored in byte-addressable
untyped memory, at least when you use void *.
For example, on a Burroughs 5000-series, where
each 48-bit word has additional "hidden" bits that specify the
type of the data in the word, the implementation
would have to have a way to ignore the type bits, and allow
access to a representation of the data as a string of
individually readable and writable bytes.
> > So, you should be able to have the same void *
> > bit pattern "point to" two different objects,
> > depending upon what type you consider it to
> > be. In the implementation I describe, that's
> > what actually happens with the non-void pointers:
> > the same bit pattern can address two different
> > parts of memory, depending upon what type
> > it is assumed to have.
>
> The implementation you described isn't legal, since it causes
> void* to loose information. You must be able to cast any
> pointer to void*, and back again, without loss of information;
> the pointer from the round trip must compare equal to the
> original pointer, and designate the same object.
In the implementation I was proposing, there would be
no loss of information, since conversion to void *
involved using the same string of bits as the typed
pointer.
However, the requirement that void * be equivalent to
unsigned char * means that my proposed implementation
would not be standard-conformant.
> If two void* actually point to two different objects, then it is
> guaranteed that they compare inequal.
Not that I doubt that you are correct, but:
Is this explicitly required in the standard?
Or is it a consequence of other requirements, e.g.,
Alberto Barbati's paragraph plus the convertability to
unsigned char *?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Alan McKenney <alan_mckenney1@yahoo.com>
Date: Mon, 29 Oct 2007 16:22:16 CST Raw View
A while back I asked on comp.lang.c++.moderated the question:
if you have pointers to two different objects and you cast them
to void *, is it legal for them to compare equal?
Many people seemed to think it was not, but none of their
explanations seemed all that convincing to me.
The situation I envisioned where this could come up is
a word-addressed machine where one word contains
multiple characters (let's say 8.)
In that case, a sensible way of representing pointers to char
types would be to have the index within the word in the bottom three
bits and the pointer to the word in the higher-order bits.
Pointers to other built-in types and to objects would be word
pointers.
Next, it would make sense to have cast to "void *" just copy the
bits in the pointer -- why do extra work?
But if you do it this way, then you could have a pointer to char
and a pointer to a double be the same, if the double's word address
was 8 times the char's word address.
If the Standard required that the void * representation of pointers
to different objects always compared unequal, it would essentially
mean that the implementation would have to use the char *
representation for the void * representation of any pointer -- meaning
conversion between void * and normal pointer would involve shifts.
So, what does the Standard require here?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Mon, 29 Oct 2007 23:23:08 GMT Raw View
Alan McKenney ha scritto:
>=20
> if you have pointers to two different objects and you cast them
> to void *, is it legal for them to compare equal?
>=20
> <snip>
>=20
> If the Standard required that the void * representation of pointers
> to different objects always compared unequal, it would essentially
> mean that the implementation would have to use the char *
> representation for the void * representation of any pointer -- meaning
> conversion between void * and normal pointer would involve shifts.
>=20
> So, what does the Standard require here?
4.10/2 says that "The result of converting a =E2=80=9Cpointer to cv T=E2=80=
=9D to a
=E2=80=9Cpointer to cv void=E2=80=9D points to the start of the storage l=
ocation where
the object of type T resides, as if the object is a most derived object
(1.8) of type T (that is, not a base class subobject)."
You can't store two most derived objects at the same location, so the
conversion to void* must produce different values for every two distinct
objects, regardless of their respective types. This may (or may not)
require the conversion from T* to void* to be something different from a
bit-wise copy. Actually, that can be said for every pointer conversion.
HTH,
Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Alan McKenney <alan_mckenney1@yahoo.com>
Date: Mon, 29 Oct 2007 21:13:29 CST Raw View
On Oct 29, 6:23 pm, AlbertoBarb...@libero.it (Alberto Ganesh Barbati)
wrote:
> Alan McKenney ha scritto:
>
>
>
> > if you have pointers to two different objects and you cast them
> > to void *, is it legal for them to compare equal?
<snip>
> 4.10/2 says that "The result of converting a "pointer to cv T" to a
> "pointer to cv void" points to the start of the storage location where
> the object of type T resides, as if the object is a most derived object
> (1.8) of type T (that is, not a base class subobject)."
But what exactly does "points to" mean?
Perhaps I'm dense, but I can only understand
"points to" to mean: what you get when you
dereference the pointer.
And since you can't dereference a void *, this
means casting it back to a pointer to a type.
In particular, as far as I know from postings
on c.l.c++.m and c.s.c++, this means casting it
back to the type that it was cast from, since
that's the only legal cast for a void *.
So, you should be able to have the same void *
bit pattern "point to" two different objects,
depending upon what type you consider it to
be. In the implementation I describe, that's
what actually happens with the non-void pointers:
the same bit pattern can address two different
parts of memory, depending upon what type
it is assumed to have.
(This is not as wierd as it sounds -- after
all, the same bit pattern on more "normal"
machines can have completely different
"values", depending upon whether the word
is regarded as a long or a float.)
I'm not sure that the paragraph that Ganesh
quotes forbids this for void * pointers:
it doesn't say anything about casting a
pointer from one type to another through
void *, nor anything about comparisons
of void * pointers arising from pointers
to different types.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Tjark Weber <tjark.weber@gmx.de>
Date: Tue, 30 Oct 2007 13:45:51 CST Raw View
On Oct 29, 11:22 pm, Alan McKenney <alan_mckenn...@yahoo.com> wrote:
> If the Standard required that the void * representation of pointers
> to different objects always compared unequal, it would essentially
> mean that the implementation would have to use the char *
> representation for the void * representation of any pointer -- meaning
> conversion between void * and normal pointer would involve shifts.
>
> So, what does the Standard require here?
3.9.2(4): "A void* shall be able to hold any object pointer. A [...]
void* shall have the same representation and alignment requirements as
a [...] char*."
Tjark
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Greg Herlihy <greghe@mac.com>
Date: Tue, 30 Oct 2007 14:17:35 CST Raw View
On 10/29/07 4:23 PM, in article hStVi.155666$%k.297514@twister2.libero.it,
"Alberto Ganesh Barbati" <AlbertoBarbati@libero.it> wrote:
> Alan McKenney ha scritto:
>>
>> if you have pointers to two different objects and you cast them
>> to void *, is it legal for them to compare equal?
>
> 4.10/2 says that "The result of converting a pointer to cv T to a
> pointer to cv void points to the start of the storage location where
> the object of type T resides, as if the object is a most derived object
> (1.8) of type T (that is, not a base class subobject)."
>
> You can't store two most derived objects at the same location, so the
> conversion to void* must produce different values for every two distinct
> objects, regardless of their respective types. This may (or may not)
> require the conversion from T* to void* to be something different from a
> bit-wise copy. Actually, that can be said for every pointer conversion.
No, two pointers to two different objects may point to the same address -
provided that the two objects do not have the same type:
struct A {};
struct B
{
A a;
};
int main()
{
B b;
void * pA = &b.a;
void * pB = &b;
assert( pB == pA); // OK
}
Otherwise, every object is guaranteed to have an address that differs from
the address of any other object - of the same type. So, the answer to the
original question is "No." C++ does not require that void* pointers to two
different objects must always compare unequal. The void* pointers are
certain to compare as unequal - only if the types of the two objects being
pointed to - are the same.
Greg
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]