 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
bgneal@gmail.com Guest
|
Posted: Wed Aug 03, 2005 9:57 am Post subject: Casting Between POD Pointers? |
|
|
I have to use an existing API to send data down a socket, into a file,
or whatever. Something like that, it doesn't really matter. Let's say
it looks like this:
int send(const unsigned char* ptr, std::size_t length);
But say I want to send a string's data. I could do either of these:
std::string s("Hello");
send(reinterpret_cast<const unsigned char*>(s.data()), s.size());
// or
const void* vp = s.data();
send(static_cast<const unsigned char*>(vp), s.size());
// or this is equivalent but leads to longer source lines:
send(static_cast<const unsigned char*>(
static_cast<const void*>(s.data())), s.size());
I've even seen people do this to make less typing:
// define this helper function once:
const unsigned char* toBytePtr(const void* vp)
{
return static_cast<const unsigned char*>(vp);
}
// and then use it everywhere (it hides the casting a bit)
send(toBytePtr(s.data()), s.size());
Herb Sutter and Andrei Alexandrescu recommend avoiding reinterpret_cast
and using the "double static_cast" (my phrase, not theirs) trick in
their C++ Coding Standards book.
So which is preferred? I'm only interested in POD pointers right now.
I can't change the API. Keep in mind I am taking everyone's advice and
burying this casting deep down into the lowest layer of my software.
Thanks.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tom Widmer Guest
|
Posted: Wed Aug 03, 2005 6:38 pm Post subject: Re: Casting Between POD Pointers? |
|
|
[email]bgneal (AT) gmail (DOT) com[/email] wrote:
| Quote: | I have to use an existing API to send data down a socket, into a file,
or whatever. Something like that, it doesn't really matter. Let's say
it looks like this:
int send(const unsigned char* ptr, std::size_t length);
But say I want to send a string's data. I could do either of these:
std::string s("Hello");
send(reinterpret_cast<const unsigned char*>(s.data()), s.size());
// or
const void* vp = s.data();
send(static_cast<const unsigned char*>(vp), s.size());
// or this is equivalent but leads to longer source lines:
send(static_cast<const unsigned char*>(
static_cast<const void*>(s.data())), s.size());
I've even seen people do this to make less typing:
// define this helper function once:
const unsigned char* toBytePtr(const void* vp)
{
return static_cast<const unsigned char*>(vp);
}
// and then use it everywhere (it hides the casting a bit)
send(toBytePtr(s.data()), s.size());
Herb Sutter and Andrei Alexandrescu recommend avoiding reinterpret_cast
and using the "double static_cast" (my phrase, not theirs) trick in
their C++ Coding Standards book.
|
That seems like an odd recommendation to me, since it makes it harder
to search for code that is performing dangerous type manipulations.
| Quote: | So which is preferred? I'm only interested in POD pointers right now.
I can't change the API. Keep in mind I am taking everyone's advice and
burying this casting deep down into the lowest layer of my software.
|
Personally, I think a single reinterpret_cast captures the intent of
the code most accurately. Why hide it?
Tom
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
tony_in_da_uk@yahoo.co.uk Guest
|
Posted: Wed Aug 03, 2005 6:39 pm Post subject: Re: Casting Between POD Pointers? |
|
|
Consider changing send to accept a void*... it's a better indication of
what send knows about the data it's handling, and you can then use
implicit conversion from data(). - Tony
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Thu Aug 04, 2005 10:46 am Post subject: Re: Casting Between POD Pointers? |
|
|
Tom Widmer wrote:
| Quote: | bgneal (AT) gmail (DOT) com wrote:
I have to use an existing API to send data down a socket,
into a file, or whatever. Something like that, it doesn't
really matter. Let's say it looks like this:
int send(const unsigned char* ptr, std::size_t length);
But say I want to send a string's data. I could do either of
these:
std::string s("Hello");
send(reinterpret_cast<const unsigned char*>(s.data()), s.size());
|
[...]
| Quote: | Herb Sutter and Andrei Alexandrescu recommend avoiding
reinterpret_cast and using the "double static_cast" (my
phrase, not theirs) trick in their C++ Coding Standards
book.
That seems like an odd recommendation to me, since it makes it
harder to search for code that is performing dangerous type
manipulations.
|
I think that's their point. In this case, the conversion is not
dangerous, and does exactly what is wanted. Portably:
reinterpret_cast is often a flag of non-portable code.
--
James Kanze GABI Software
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Martin Bonner Guest
|
Posted: Thu Aug 04, 2005 10:46 am Post subject: Re: Casting Between POD Pointers? |
|
|
[email]tony_in_da_uk (AT) yahoo (DOT) co.uk[/email] wrote:
| Quote: | Consider changing send to accept a void*
|
Except that the OP specified that he is unable to change "send"!
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Martin Bonner Guest
|
Posted: Thu Aug 04, 2005 10:47 am Post subject: Re: Casting Between POD Pointers? |
|
|
Tom Widmer wrote:
| Quote: | bgneal (AT) gmail (DOT) com wrote:
I have to use an existing API to send data down a socket, into a file,
or whatever. Something like that, it doesn't really matter.
|
[snip]
| Quote: | // define this helper function once:
const unsigned char* toBytePtr(const void* vp)
{
return static_cast<const unsigned char*>(vp);
}
// and then use it everywhere (it hides the casting a bit)
send(toBytePtr(s.data()), s.size());
Herb Sutter and Andrei Alexandrescu recommend avoiding reinterpret_cast
and using the "double static_cast" (my phrase, not theirs) trick in
their C++ Coding Standards book.
That seems like an odd recommendation to me, since it makes it harder
to search for code that is performing dangerous type manipulations.
|
Except that reinterpret_cast of a pointer to unsigned char * is not a
(particularly) dangerous type manipulation. The standard specifically
blesses accessing arbitary memory as unsigned char (subject to a lot of
caveats of course).
| Quote: |
So which is preferred? I'm only interested in POD pointers right now.
I can't change the API. Keep in mind I am taking everyone's advice and
burying this casting deep down into the lowest layer of my software.
Personally, I think a single reinterpret_cast captures the intent of
the code most accurately. Why hide it?
|
I think that toBytePtr() captures the intent even more clearly. It
doesn't say cause the reader to go "RED ALERT - TRICKY CODE AHEAD ...
oh OK, mostly harmless".
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Thu Aug 04, 2005 1:30 pm Post subject: Re: Casting Between POD Pointers? |
|
|
In article <1123148032.079965.102760 (AT) z14g2000cwz (DOT) googlegroups.com>,
Martin Bonner <martinfrompi (AT) yahoo (DOT) co.uk> writes
| Quote: |
[email]tony_in_da_uk (AT) yahoo (DOT) co.uk[/email] wrote:
Consider changing send to accept a void*
Except that the OP specified that he is unable to change "send"!
|
But you do not need to modify send, just overload it to take a
std::string const & and do whatever you need to do as its
implementation. If you are worried about performance, declare it inline
and provide the implementation where the compiler can see it.
Of course that does not address the OP's original question but it does
provide a single point where the problem can be addressed.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
tony_in_da_uk@yahoo.co.uk Guest
|
Posted: Thu Aug 04, 2005 5:03 pm Post subject: Re: Casting Between POD Pointers? |
|
|
Francis has it precisely right. Often when dealing with legacy
interfaces (particularly C ones without const correctness), it's useful
to have wrapping functions (preferably in a namespace) which change
types, standardise calling conventions, wrapping the original
functions, and possibly throwing exceptions . Cheers, Tony
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tom Widmer Guest
|
Posted: Thu Aug 04, 2005 5:03 pm Post subject: Re: Casting Between POD Pointers? |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
| Quote: | Tom Widmer wrote:
Herb Sutter and Andrei Alexandrescu recommend avoiding
reinterpret_cast and using the "double static_cast" (my
phrase, not theirs) trick in their C++ Coding Standards
book.
That seems like an odd recommendation to me, since it makes it
harder to search for code that is performing dangerous type
manipulations.
I think that's their point. In this case, the conversion is not
dangerous, and does exactly what is wanted.
|
Presumably that is true of any use of reinterpret_cast in working code!
Portably:
| Quote: | reinterpret_cast is often a flag of non-portable code.
|
Sending a char string to another program is non-portable in general.
What about extended characters, code pages, non-ascii machines, non
8-bit chars, etc? Why is this any different than reinterpret_casting a
int*?
Generally, casting pointers to unsigned char* to access their bytes
(for IO and IPC, generally) is the main reason I ever use
reinterpret_cast (and I use it with care, to communicate with processes
compiled with the same compiler and to write out temporary files). If I
eliminated it from there (where it is non-portable, even for char), I
wouldn't use it at all.
Tom
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Fri Aug 05, 2005 3:10 pm Post subject: Re: Casting Between POD Pointers? |
|
|
Tom Widmer wrote:
| Quote: | kanze (AT) gabi-soft (DOT) fr wrote:
Tom Widmer wrote:
Herb Sutter and Andrei Alexandrescu recommend avoiding
reinterpret_cast and using the "double static_cast" (my
phrase, not theirs) trick in their C++ Coding Standards
book.
That seems like an odd recommendation to me, since it
makes it harder to search for code that is performing
dangerous type manipulations.
I think that's their point. In this case, the conversion is
not dangerous, and does exactly what is wanted.
Presumably that is true of any use of reinterpret_cast in working code!
|
Hopefully, that the reinterpret_cast does exactly what is
wanted, at least. It remains dangerous.
| Quote: | Portably:
reinterpret_cast is often a flag of non-portable code.
Sending a char string to another program is non-portable in
general.
|
Not really. It depends on what you put in the string.
| Quote: | What about extended characters, code pages, non-ascii
machines, non 8-bit chars, etc? Why is this any different than
reinterpret_casting a int*?
|
Obviously, if you don't know what you've put in the string, you
are going to have problems. In the case in question, we're
talking about (binary) formatted data in a buffer of unsigned
char[]. You've put it into unsigned char, because it's becoming
raw memory. But that raw memory contains what you have put into
it, and presumably, what you have put into it corresponds to
what the format specifications require.
The issues you raise only affect character data, either from
string literals or from some form of character input. In which
case, you doubtlessly have a char[], and don't need the cast.
One could arguably say that code without the cast isn't
portable.
| Quote: | Generally, casting pointers to unsigned char* to access their
bytes (for IO and IPC, generally) is the main reason I ever
use reinterpret_cast (and I use it with care, to communicate
with processes compiled with the same compiler and to write
out temporary files). If I eliminated it from there (where it
is non-portable, even for char), I wouldn't use it at all.
|
Good.
That's probably true for my code as well. But it's not a
general rule; my understanding of reinterpret_cast is that it is
intended for very machine specific things, such as you might
find in an OS kernel or a device driver. Still...
The important thing (assuming the code works, of course) is that
you give the correct message. I don't think that the default
message of reinterpret_cast is quite correct, but if you are
mainly (or exclusively) concerned with application programming,
and have no other use for it, defining this use as "appropriate"
in your coding guidelines would seem reasonable.
--
James Kanze GABI Software
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
David Abrahams Guest
|
Posted: Sat Aug 06, 2005 11:16 am Post subject: Re: Casting Between POD Pointers? |
|
|
"Tom Widmer" <tom_usenet (AT) hotmail (DOT) com> writes:
| Quote: | Herb Sutter and Andrei Alexandrescu recommend avoiding reinterpret_cast
and using the "double static_cast" (my phrase, not theirs) trick in
their C++ Coding Standards book.
That seems like an odd recommendation to me, since it makes it harder
to search for code that is performing dangerous type manipulations.
|
Most uses of reinterpret_cast have technically nonportable,
implementation-defined behavior. For example,
struct foo
{
int x;
};
struct bar
{
int y;
double z;
};
bar bq;
#ifdef NONPORTABLE
// implementation-defined
foo* fire = reinterpret_cast<foo*>(&bq);
// technically nonportable: does it crash?
fire->x = 1;
#else // The following is portable, though
// equivalent to:
//
// void* water = &bq;
//
// 4.10/2 says that water points at the beginning of bq's storage.
void* water = static_cast<void*>(&bq);
// This is legal by various implications in the standard. See, for
// example: POD, offsetof, memcpy
foo* earth = static_cast<foo*>(water);
earth->x = 1; // now bq.y == 1
#endif
BTW, most people seem to think of static_cast's as not being
"dangerous type manipulations," but the reasons escape me. You can
certainly do plenty of damage with a static_cast. I'd rather see a
const_cast than a static_cast any day of the week.
Obviously you can't use a const_cast where a static_cast would work,
and vice-versa. That's good: it means my code clearly separates the
most dangerous bits from the rest.
HTH,
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Sun Aug 07, 2005 1:36 am Post subject: Re: Casting Between POD Pointers? |
|
|
David Abrahams wrote:
| Quote: |
// implementation-defined
foo* fire = reinterpret_cast<foo*>(&bq);
|
Minor point: that's one of a couple of cases where the behavior of
reinterpret_cast is unpsecified (except that if the object types have
suitable alignments, you can cast this result back to the original
pointer type and get the original value).
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gabriel Dos Reis Guest
|
Posted: Sun Aug 07, 2005 1:37 am Post subject: Re: Casting Between POD Pointers? |
|
|
David Abrahams <dave (AT) boost-consulting (DOT) com> writes:
| Quote: | "Tom Widmer" <tom_usenet (AT) hotmail (DOT) com> writes:
Herb Sutter and Andrei Alexandrescu recommend avoiding reinterpret_cast
and using the "double static_cast" (my phrase, not theirs) trick in
their C++ Coding Standards book.
That seems like an odd recommendation to me, since it makes it harder
to search for code that is performing dangerous type manipulations.
Most uses of reinterpret_cast have technically nonportable,
implementation-defined behavior. For example,
struct foo
{
int x;
};
struct bar
{
int y;
double z;
};
bar bq;
#ifdef NONPORTABLE
// implementation-defined
foo* fire = reinterpret_cast<foo*>(&bq);
// technically nonportable: does it crash?
fire->x = 1;
#else // The following is portable, though
// equivalent to:
//
// void* water = &bq;
//
// 4.10/2 says that water points at the beginning of bq's storage.
void* water = static_cast<void*>(&bq);
// This is legal by various implications in the standard. See, for
// example: POD, offsetof, memcpy
foo* earth = static_cast<foo*>(water);
earth->x = 1; // now bq.y == 1
|
That escapes me. I've gone through POD, offsetof and memcpy but I
can't construct the chain of logical inference why it is valid.
This is valid though
*static_cast<int*>(wather) = 1; // now bq.y == 1
--
Gabriel Dos Reis
[email]gdr (AT) integrable-solutions (DOT) net[/email]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|