Topic: Few questions about pointer conversions in standard
Author: "Me" <anti_spam_email2003@yahoo.com>
Date: Sun, 24 Apr 2005 20:23:19 CST Raw View
1.
4.10/2 - what is the rationale of including the words "as if the object
is a most derived object of type T"? It seems redundant to me.
2.
int *foo = 0;
void *bar = foo;
The wording of 4.10/2 doesn't seem to say if bar == ((void*)0) even
though C does (6.3.2.3/4)
3.
Similar question about static_cast<void*>(foo) == ((void*)0). I guess
5.2.9/10 kind of implies this will hold, but I'm not language lawyer
enough to decide if it is true or not.
4.
Foo *foo = <whatever>;
void *v = foo;
Foo *sfoo = static_cast<Foo*>(v);
Foo *rfoo = reinterpret_cast<Foo*>(v);
Does sfoo == rfoo, why or why not? Assume Foo is an object type (can be
non-POD or even an incomplete type).
To make this simpler we know that foo == sfoo because of 5.2.9/10, so
we just need to prove foo == rfoo
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net
Date: Mon, 25 Apr 2005 10:20:03 CST Raw View
Me wrote:
> 1.
> 4.10/2 - what is the rationale of including the words "as if the
object
> is a most derived object of type T"? It seems redundant to me.
struct A { int a; };
struct B { int b; };
struct C : A, B { int c; };
C obj;
A *pa = (A*)&obj;
B *pb = (B*)&obj;
void *p = (void*)pa;
// At this point, p points at the start of the A base sub-object of
obj.
p = (void*)pb;
// At this point, p points at the start of the B base sub-object of
obj.
If the wording you consider redundant were removed, then since 'obj' is
an object of type A, and also an object of type B, both assignments to
'p' would be required to point at the beginning of 'obj', rather than
at the beginnings of the corresponding sub-objects. If you think for a
while about the implications of such a requirement, I think you'll see
why the those words were added.
> 2.
> int *foo = 0;
> void *bar = foo;
>
> The wording of 4.10/2 doesn't seem to say if bar == ((void*)0) even
> though C does (6.3.2.3/4)
I agree.
> 3.
> Similar question about static_cast<void*>(foo) == ((void*)0). I guess
> 5.2.9/10 kind of implies this will hold, but I'm not language lawyer
> enough to decide if it is true or not.
No, 5.2.9/10 doesn't apply, because 'void*' isn't the pointer's
original type.
> 4.
> Foo *foo = <whatever>;
> void *v = foo;
> Foo *sfoo = static_cast<Foo*>(v);
> Foo *rfoo = reinterpret_cast<Foo*>(v);
>
> Does sfoo == rfoo, why or why not? Assume Foo is an object type (can
be
> non-POD or even an incomplete type).
The standard says that if you reinterpret_cast from one pointer type to
another, and back again, you get the same pointer value. However, it
says nothing about where the intermediate pointer points. The
initialization of v was performed using the equivalent of
static_cast<>, so 5.2.9p10 applies to guarantee that sfoo==foo, but
5.2.10p7 doesn't apply to guarantee that rfoo==foo. It's unclear
whether 5.2.10p7 even applies at all, since v is not a pointer to an
object type (though it is arguably a pointer to an object). Therefore,
there's no guarantee that sfoo==rfoo.
The de-facto standard for conversions between pointer types (where not
otherwise specified), is that the converted pointer points at the same
memory location as the original, unless alignment requirements prevent
it from doing so, in which case one of the two nearest correctly
aligned locations is chosen (for pointers near the end of the available
memory space, "nearest" might be interpreted in a fashion that wraps
around to the beginning of memory). The de-jure standard gives no such
guarantees.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Barbati)
Date: Tue, 26 Apr 2005 05:21:55 GMT Raw View
Me wrote:
> 1.
> 4.10/2 - what is the rationale of including the words "as if the object
> is a most derived object of type T"? It seems redundant to me.
The storages of base-class subobjects and most-derived objects may have
different layouts (in particular, they often have different sizes).
> 2.
> int *foo =3D 0;
> void *bar =3D foo;
>=20
> The wording of 4.10/2 doesn't seem to say if bar =3D=3D ((void*)0) even
> though C does (6.3.2.3/4)
That's curious, because in 4.10/3 (conversion from =93pointer to cv D=94 =
to
=93pointer to cv B=94) it's said explicitly: "The null pointer value is
converted to the null pointer value of the destination type." As it's
put there, it apparently doesn't apply to the conversion to =93pointer to
cv void=94 also. Whether that's intentional or not, I don't know.
> 3.
> Similar question about static_cast<void*>(foo) =3D=3D ((void*)0). I gue=
ss
> 5.2.9/10 kind of implies this will hold, but I'm not language lawyer
> enough to decide if it is true or not.
I don't think 5.2.9/10 implies that, but I'm not a language lawyer too.
> 4.
> Foo *foo =3D <whatever>;
> void *v =3D foo;
> Foo *sfoo =3D static_cast<Foo*>(v);
> Foo *rfoo =3D reinterpret_cast<Foo*>(v);
>=20
> Does sfoo =3D=3D rfoo, why or why not? Assume Foo is an object type (ca=
n be
> non-POD or even an incomplete type).
>=20
> To make this simpler we know that foo =3D=3D sfoo because of 5.2.9/10, =
so
> we just need to prove foo =3D=3D rfoo
If I interpret the standard correctly, the only statement that would
provide such guarantee is 5.2.10/7, but that only applies if the types
involved are object types with compatible alignements. As in our case
the "source" type is void, I think the value of rfoo is to be considered
an unspecified implementation-defined value, which is not required to
satisfy foo =3D=3D rfoo (although that might happen, of course ;)
Alberto
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: "Me" <anti_spam_email2003@yahoo.com>
Date: 26 Apr 2005 05:30:17 GMT Raw View
> struct A { int a; };
> struct B { int b; };
> struct C : A, B { int c; };
>
> C obj;
> A *pa = (A*)&obj;
> B *pb = (B*)&obj;
> void *p = (void*)pa;
> // At this point, p points at the start of the A base sub-object of
> obj.
>
> p = (void*)pb;
> // At this point, p points at the start of the B base sub-object of
> obj.
>
> If the wording you consider redundant were removed, then since 'obj'
is
> an object of type A, and also an object of type B, both assignments
to
> 'p' would be required to point at the beginning of 'obj', rather than
> at the beginnings of the corresponding sub-objects. If you think for
a
> while about the implications of such a requirement, I think you'll
see
> why the those words were added.
Unless I'm missing something, your code is the equivalent of doing a
static_cast to void * and not a standard conversion to void *, and the
standard doesn't say where it points to in this case. This is cue for
somebody to jump in and correct me because that seems very
counterintuitive.
I'm not trying to argue whether or not to remove that sentence from the
standard, I'm just wondering if that part of the sentence really adds
anything because "points to the start of the storage location where the
object of type T resides" seems pretty clear to me and doesn't sound
like it would point to the C object in your example.
> > int *foo = 0;
> > void *bar = foo;
> >
> > The wording of 4.10/2 doesn't seem to say if bar == ((void*)0) even
> > though C does (6.3.2.3/4)
>
> I agree.
>
> > Similar question about static_cast<void*>(foo) == ((void*)0). I
guess
> > 5.2.9/10 kind of implies this will hold, but I'm not language
lawyer
> > enough to decide if it is true or not.
>
> No, 5.2.9/10 doesn't apply, because 'void*' isn't the pointer's
> original type.
I noticed a defect report hasn't been filed for these two, is this
really supposed to be intentional behavior?
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: "Me" <anti_spam_email2003@yahoo.com>
Date: Tue, 26 Apr 2005 15:56:58 CST Raw View
> Unless I'm missing something, your code is the equivalent of doing a
> static_cast to void * and not a standard conversion to void *, and
the
> standard doesn't say where it points to in this case. This is cue for
> somebody to jump in and correct me because that seems very
> counterintuitive.
Brain fart... 5.2.9/2, I realized that like 2 minutes after I posted
but there is a 24 hour delay in google.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: wade@stoner.com
Date: Tue, 26 Apr 2005 15:54:57 CST Raw View
Me wrote:
> [JK wrote]:
> > struct A { int a; };
> > struct B { int b; };
> > struct C : A, B { int c; };
> >
> > C obj;
> > A *pa = (A*)&obj;
> > void *p = (void*)pa;
> > // At this point, p points at the start of the A base sub-object of
> > obj.
> Unless I'm missing something, your code is the equivalent of doing a
> static_cast to void * and not a standard conversion to void *, and
the
> standard doesn't say where it points to in this case. This is cue for
> somebody to jump in and correct me because that seems very
> counterintuitive.
AFAICT static cast does the standard conversion in this case. In
particular
p = static_cast<void*>(pa);
means the same thing (in this case) as
void* t(pa);
p = t;
and I believe the initialization of 't' uses a standard conversion.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net
Date: Tue, 26 Apr 2005 15:59:23 CST Raw View
Me wrote:
> > struct A { int a; };
> > struct B { int b; };
> > struct C : A, B { int c; };
> >
> > C obj;
> > A *pa = (A*)&obj;
> > B *pb = (B*)&obj;
> > void *p = (void*)pa;
> > // At this point, p points at the start of the A base sub-object of
> > obj.
> >
> > p = (void*)pb;
> > // At this point, p points at the start of the B base sub-object of
> > obj.
> >
> > If the wording you consider redundant were removed, then since
'obj'
> is
> > an object of type A, and also an object of type B, both assignments
> to
> > 'p' would be required to point at the beginning of 'obj', rather
than
> > at the beginnings of the corresponding sub-objects. If you think
for
> a
> > while about the implications of such a requirement, I think you'll
> see
> > why the those words were added.
>
> Unless I'm missing something, your code is the equivalent of doing a
> static_cast to void * and not a standard conversion to void *, and
the
> standard doesn't say where it points to in this case. This is cue for
> somebody to jump in and correct me because that seems very
> counterintuitive.
I'm sorry; I've written too much C, and not enough C++, so I over-used
C-style casts. What I should have written was the following:
A *pa(&obj);
B *pb(&obj);
void *p(pa);
p = static_cast<void*>pb;
However, 5.4p5 gurantees that the C-style casts I actually used are all
treated as static_cast<>s, which, as I argue below, is precisely what I
intended.
5.2.9p2 says that static_cast<T>(e) is permitted if a declaration T
t(e) would be legal, and performs the same conversion that such a
declaration would cause to occur.
The last bullet item under 8.5p14 indicates that such a declaration
would cause the standard conversions to occur. So in this case
static_cast<> causes a standard conversion.
4.10p2 guarantees that the standard conversion to void* results in a
pointer pointing at the start of the object.
> I'm not trying to argue whether or not to remove that sentence from
the
> standard, I'm just wondering if that part of the sentence really adds
> anything because "points to the start of the storage location where
the
> object of type T resides" seems pretty clear to me and doesn't sound
> like it would point to the C object in your example.
Well, the C object is an object of type B, so I don't see how (without
that wording), it could point anywhere else but at the start of the
object.
.
> > No, 5.2.9/10 doesn't apply, because 'void*' isn't the pointer's
> > original type.
>
> I noticed a defect report hasn't been filed for these two, is this
> really supposed to be intentional behavior?
I've never understood the failure of the standard to be more specific
about where a pointer points at after conversion to a different type. I
can't come up for any obvious reason for allowing anything other than
the most obvious and common implementation: the resulting pointer
points a the same location in memory as the orginal pointer, if
alignment requirements allow it to do so. That is what the standard
actually requires in several specific cases However, in the general
case where the target type is neither special (void*) nor has a special
relationship to the source type, the standard is silent on the issue of
where the resulting pointer points.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]