C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

void pointer conversion

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
sweetiebentley@hotmail.co
Guest





PostPosted: Wed Dec 15, 2004 1:32 am    Post subject: void pointer conversion Reply with quote



What is the "accepted method" of converting/casting a void pointer to
another type? For example, in motif programming, XtPointers are used
to pass data to callback functions. This type, void*, can be used to
represent primitives or pointers of (I guess) any type. Of course, a
cast usually results in a compiler warning. I can eliminate the
warning by using a union hack, but I guess that's not the "accepted
method". So what is?
Joe


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Jack Klein
Guest





PostPosted: Wed Dec 15, 2004 10:46 am    Post subject: Re: void pointer conversion Reply with quote



On 14 Dec 2004 20:32:57 -0500, [email]sweetiebentley (AT) hotmail (DOT) com[/email] wrote in
comp.lang.c++.moderated:

Quote:
What is the "accepted method" of converting/casting a void pointer to
another type? For example, in motif programming, XtPointers are used
to pass data to callback functions. This type, void*, can be used to
represent primitives or pointers of (I guess) any type. Of course, a
cast usually results in a compiler warning. I can eliminate the
warning by using a union hack, but I guess that's not the "accepted
method". So what is?
Joe

I don't understand the "a cast usually results in a warning".

In C++, a pointer to void is guaranteed to be able to hold a pointer
to any type of object. You can convert a pointer to any object type
to pointer to void, then convert it back to a pointer to the original
type, and it is guaranteed to point to the same object. So you don't
have to guess.

In C++, unlike C, a cast is required to convert a pointer to void to
any other pointer type, but as long as the original and final pointers
are of the same type, and match the actual type of the value pointed
to, the results are correct.

What compiler warns about:

void *vp = /* something */;
int *ip = vp;

Or are you trying to convert between pointers to void and pointers to
function type? There is no such defined conversion.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Allan W
Guest





PostPosted: Thu Dec 16, 2004 1:46 pm    Post subject: Re: void pointer conversion Reply with quote



Your question about the code doesn't seem to match the rest of your
article! But the answer is:

Microsoft Visual C++ gives error C2440: 'initializing': cannot convert
from 'void *' to 'int *'
I suspect most other compilers would warn about this too.
Add the cast and the warning goes away:
int *ip = static_cast<int*>(vp);

To answer the OP, the "accepted method" of casting a void pointer to
another type depends on the reason for the cast, but in most cases
static_cast is the way to go.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
richard@ex-parrot.com
Guest





PostPosted: Fri Dec 17, 2004 7:10 pm    Post subject: Re: void pointer conversion Reply with quote

Allan W wrote:

Quote:
To answer the OP, the "accepted method" of casting a void pointer to
another type depends on the reason for the cast, but in most cases
static_cast is the way to go.

One case in which static_cast is *not* the way to go, is when you are
converting from void* to a function pointer type, e.g.

void* p;
int (*fp)() = static_cast<int(*)()>(p); // Erorr

This is because C++ does not guarantee that a void* is big enough to
hold a function pointer. (In practice it almost always will be because
many other APIs including POSIX and the Win32 API require this.)
--
Richard Smith


[ 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





PostPosted: Tue Dec 21, 2004 12:57 am    Post subject: Re: void pointer conversion Reply with quote

[email]richard (AT) ex-parrot (DOT) com[/email] wrote:
Quote:
Allan W wrote:

To answer the OP, the "accepted method" of casting a void pointer
to
another type depends on the reason for the cast, but in most cases
static_cast is the way to go.

One case in which static_cast is *not* the way to go, is when you are
converting from void* to a function pointer type, e.g.

void* p;
int (*fp)() = static_cast<int(*)()>(p); // Erorr

This is because C++ does not guarantee that a void* is big enough to
hold a function pointer. (In practice it almost always will be
because many other APIs including POSIX and the Win32 API require
this.)

Sort of. You're right that neither C nor C++ allow any type of
conversion between a void* and a pointer to function (exception in the
special case of ((void*)0) in C). So as far as the C++ standard is
concerned, neither static_cast, nor reinterpret_cast, nor a C style
cast
nor a conversion using functional notation are allowed here.

X/Open System (not Posix) requires that you be able to convert a void*
into a pointer to function, in order to use the results of a at least
one request. I'm not aware of anything similar in Windows, but I'm not
that familiar with Windows, either.

X/Open System also totally ignores C++, so it doesn't say whether you
need a static_cast or a reinterpret_cast to do the conversion. For
that
matter, although the X/Open System Interface returns a void* which
contains a pointer to a function, I don't think that the Posix
interface
specifies how you are supposed to do the conversion (since there is no
such conversion in standard C nor in standard C++); the example code
uses:

int (*fptr)( int ) ;
*(void **)(&fptr) = dlsym(handle, "my_function");

which suggests that 1) pointers to functions and pointers to objects do
have the same size, but 2) there is no way in C (and thus logically in
C++) to convert them correctly, even with Posix extensions; you must
jump through hoops by casting a pointer to the address (or presumably
memcpy). The C++ equivalent to this is quite obviously a
reinterpret_cast, i.e. :
*reinterpret_cast< void** >( &fptr ) = dlsym( handle, "my_function"
) ;

In practice, most C compilers for X/Open System also support a
straightforeward C style cast, e.g. (int (*)(int))dlsym...), although
as
far as I can tell, this is neither necessary nor even allowed by the X
Open System specification. This extension is so wide-spread as to be a
de facto standard, even though C explicitly forbids it, and X Open
System does nothing to even suggest that they differ from C here. One
could argue that a good compiler would not support it, but given the
ubiquity of the extension, I'm not sure; banning it would probably
break
a lot of user code, and would surely keep the phones ringing on the
support desk:-). There's also a question of backward's compatibility
--
while Posix may require a convertion of the address, the documentation
for Solaris, for example, uses a direct C style cast, e.g.:
fptr = (int (*)(int))dlsym ...
This logically maps to a reinterpret_cast in C++. But again, a
compiler
is not required to accept it (unless it claims to be Solaris
compliant).

(It definitely should not work if you have strict standard C turned on;
by default, of course, most compilers will start with a mixture of
standard C, standard Posix or Windows, maybe X/Open System and possibly
some private extensions activated.)

As a quality of implementation issue, any C++ compiler which allows the
C style cast should also allow a reinterpret_cast -- I can't see any
reason for static_cast instead. And a C++ compiler which doesn't allow
the C style cast will obviously not allow any C++ style cast. But in
portable code, you will use something like the example in the X Open
System specification, and unless the source includes <dlfcn.h> (which
only works in an X Open System environment), I would add an assert
immediately in front of the case, along the lines of:
assert( sizeof( int (*)() ) == sizeof( void* ) ) ;
I don't like deferring this sort of check to run-time, but better late
than never.

--
James Kanze GABI Software http://www.gabi-soft.fr
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
Allan W
Guest





PostPosted: Wed Dec 22, 2004 8:59 am    Post subject: Re: void pointer conversion Reply with quote

Quote:
Allan W wrote:
To answer the OP, the "accepted method" of casting a void pointer
to
another type depends on the reason for the cast, but in most cases
static_cast is the way to go.

[email]richard (AT) ex-parrot (DOT) com[/email] wrote:
Quote:
One case in which static_cast is *not* the way to go, is when you are
converting from void* to a function pointer type, e.g.

void* p;
int (*fp)() = static_cast<int(*)()>(p); // Erorr

This is because C++ does not guarantee that a void* is big enough to
hold a function pointer. (In practice it almost always will be
because
many other APIs including POSIX and the Win32 API require this.)

In which case, the problem was casting the function pointer to a
void pointer in the first place.

The question was what type of cast to use in this situation. If
void* happens to be large enough, on your platform, to point to a
function, then I'd still use a static_cast. If void* is NOT large
enough to point to a function, then there isn't ANY type of cast
that is guaranteed to get back the missing information!


[ 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





PostPosted: Thu Dec 23, 2004 9:45 pm    Post subject: Re: void pointer conversion Reply with quote

Allan W wrote:
Quote:
Allan W wrote:
To answer the OP, the "accepted method" of casting a void pointer
to another type depends on the reason for the cast, but in most
cases static_cast is the way to go.

[email]richard (AT) ex-parrot (DOT) com[/email] wrote:
One case in which static_cast is *not* the way to go, is when you
are converting from void* to a function pointer type, e.g.

void* p;
int (*fp)() = static_cast<int(*)()>(p); // Erorr

This is because C++ does not guarantee that a void* is big enough
to
hold a function pointer. (In practice it almost always will be
because many other APIs including POSIX and the Win32 API require
this.)

In which case, the problem was casting the function pointer to a void
pointer in the first place.

The pointer came from a system routine. How the system routine got it
is not said -- it could have been assembler code for all we know.

In fact, of course, at the level of system routines, the distinction
between functions and data is a little bit vague. The system allocates
a suitably aligned array of bytes (unsigned char, or whatever), and
reads data from a file into it. It then reads other data from the file
(the symbol table), adds the address where it read the data to it, and
turns this into the address of a function. Or not -- in the case of
Posix, it asks the calling application to do this last step.

In cases where function pointers don't fit into a void*, the system
routine must do something different. In a case like middle model on
the
older Intel systems, of course, the system routine would simply use far
pointers. Of course, in such cases, the system cannot return the
address of a function in a void*.

Quote:
The question was what type of cast to use in this situation. If void*
happens to be large enough, on your platform, to point to a function,
then I'd still use a static_cast.

The standard says that the conversion is an error. For all possible
types of casts. In practice, you'll use whatever works:-) -- with Sun
CC, it's reinterpret_cast, and the apparently portable Posix solution
(taken from an example, however, and not normative text) would involve
taking the address of the target pointer, casting it, and dereferencing
the results, e.g.:

*(void**)(&fptr) = dlsym( ... ) ;

This IS a legal conversion, although the results are implementation
defined. In terms of C++ casts, it is a reinterpretation_cast.

Quote:
If void* is NOT large enough to point to a function, then there isn't
ANY type of cast that is guaranteed to get back the missing
information!

That's for sure:-).

The one case I know where this is necessary is with the return value of
dlsym, in X Open Systems (the XSI extension to Posix). The Rationale
to
this function is worth quoting in its entirity:

The ISO C standard does not require that pointers to functions can
be cast back and forth to pointers to data. Indeed, the ISO C
standard does not require that an object of type void * can hold a
pointer to a function. Implementations supporting the XSI
extension,
however, do require that an object of type void * can hold a
pointer
to a function. The result of converting a pointer to a function
into
a pointer to another data type (except void *) is still undefined,
however. Note that compilers conforming to the ISO C standard are
required to generate a warning if a conversion from a void *
pointer
to a function pointer is attempted as in:

fptr = (int (*)(int))dlsym(handle, "my_function");

Due to the problem noted here, a future version may either add a
new
function to return function pointers, or the current interface may
be deprecated in favor of two new functions: one that returns data
pointers and the other that returns function pointers.

Note the second and third sentences.

My only complaint now is that this information only appears way down in
the Rationale, and not in the actual description of the function.

In the mean time, regardless of what the specifications say, C code
like
that in the rationale is frequent, and no compiler implementor is going
to risk breaking it, regardless of what the standards say. Note too
that the C standard only requires a "diagnostic" -- and a warning
qualifies as a diagnostic if documented as such.

The only open question is whether the (illegal) C style cast maps to an
(illegal) reinterpret_cast or an (illegal) static_cast. If I were
implementing a compiler, I'd lean to the reinterpret_cast, but I can
see
that there are good arguments for both.

--
James Kanze GABI Software http://www.gabi-soft.fr
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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.