cast function pointer to void*

W

WaterWalk

*Hope this thread doesn't violate this group's rule*

I found the following code in the GNOME's glib-2.12 source:

/* In gclosure.c */
GClosure*
g_cclosure_new (GCallback callback_func,
gpointer user_data,
GClosureNotify destroy_data)
{
......
/* ((GCClosure*) closure)->callback is of type gpointer */
((GCClosure*) closure)->callback = (gpointer) callback_func;
}

Here a GCallback is cast to a gpointer type. The definition of
GCallback and gpointer are as follows:
typedef void (*GCallback) (void); /* in gclosure.h */
typedef void* gpointer; /* in gtypes.h */

So the result is that a (void (*)(void)) is cast to (void*). However a
search of this group and c99 standard indicates that casting a
function pointer to a void pointer is undefined behavior. I wonder if
the glib practice is preferable.
 
G

Guest

WaterWalk said:
*Hope this thread doesn't violate this group's rule*

I found the following code in the GNOME's glib-2.12 source:
[...]
So the result is that a (void (*)(void)) is cast to (void*). However a
search of this group and c99 standard indicates that casting a
function pointer to a void pointer is undefined behavior.

It's a constraint violation, actually, meaning it might not compile, or
if it does compile, the /entire/ program is outside of the scope of the
C standard (even if the conversion would never actually be performed).
I wonder if
the glib practice is preferable.

Preferable to what? There's simply no way in standard C to reliably
convert function pointers to object pointers, so if there is a
legitimate reason to do so (I don't know if there is a good reason
here), it must be done using an implementation-specific extension.
 
R

Richard Bos

WaterWalk said:
*Hope this thread doesn't violate this group's rule*

The code is off-topic, but the question you ask about it - basically,
_is_ this ISO C - is on-topic.
/* In gclosure.c */
GClosure*
g_cclosure_new (GCallback callback_func,
gpointer user_data,
GClosureNotify destroy_data)
{
......
/* ((GCClosure*) closure)->callback is of type gpointer */
((GCClosure*) closure)->callback = (gpointer) callback_func;
}

Here a GCallback is cast to a gpointer type. The definition of
GCallback and gpointer are as follows:
typedef void (*GCallback) (void); /* in gclosure.h */
typedef void* gpointer; /* in gtypes.h */

So the result is that a (void (*)(void)) is cast to (void*). However a
search of this group and c99 standard indicates that casting a
function pointer to a void pointer is undefined behavior. I wonder if
the glib practice is preferable.

Yes, it's undefined behaviour; and therefore, no, it's not preferable.
Nor is it necessary, since ISO C requires that all function pointer
types can be converted to and from one another without loss of
information.

Richard
 
G

Guest

Harald said:
WaterWalk said:
*Hope this thread doesn't violate this group's rule*

I found the following code in the GNOME's glib-2.12 source:
[...]
So the result is that a (void (*)(void)) is cast to (void*). However a
search of this group and c99 standard indicates that casting a
function pointer to a void pointer is undefined behavior.

It's a constraint violation, actually, meaning it might not compile, or
if it does compile, the /entire/ program is outside of the scope of the
C standard (even if the conversion would never actually be performed).

Actually... I know it's treated as a constraint violation by multiple
compilers, but I can't seem to find any wording in the standard that
says so. I'd appreciate it if anyone could point it out.
 
J

Jack Klein

*Hope this thread doesn't violate this group's rule*

I found the following code in the GNOME's glib-2.12 source:

/* In gclosure.c */
GClosure*
g_cclosure_new (GCallback callback_func,
gpointer user_data,
GClosureNotify destroy_data)
{
......
/* ((GCClosure*) closure)->callback is of type gpointer */
((GCClosure*) closure)->callback = (gpointer) callback_func;
}

Here a GCallback is cast to a gpointer type. The definition of
GCallback and gpointer are as follows:
typedef void (*GCallback) (void); /* in gclosure.h */
typedef void* gpointer; /* in gtypes.h */

So the result is that a (void (*)(void)) is cast to (void*). However a
search of this group and c99 standard indicates that casting a
function pointer to a void pointer is undefined behavior. I wonder if
the glib practice is preferable.

Unfortunately, there is a lot of code that is based on the fact that
on many implementations pointers to functions and pointers to void
have the same size and number of value bits. It is, was, and always
has been sloppy programming with no real justification whatsoever.

This behavior is now required in both the Windows and POSIX APIs, for
example.

But I don't understand your question. You post one code sample which
you state if from glib source, then ask is the glib practice is
preferable. Preferable to what alternative?
 
S

Spoon

Jack said:
Unfortunately, there is a lot of code that is based on the fact that
on many implementations pointers to functions and pointers to void
have the same size and number of value bits. It is, was, and always
has been sloppy programming with no real justification whatsoever.

This behavior is now required in both the Windows and POSIX APIs, for
example.

As far as I remember, on IA-64/Linux, object pointers are 64 bits wide
while function pointers are 128 bits wide.

cf. http://www.gelato.unsw.edu.au/archives/linux-ia64/0201/2679.html

"On IA64 and PPC64 the function pointer does not reference the function
itself, instead it points to a function descriptor. The function
descriptor contains a pointer to the function code plus additional data
such as a pointer to the global data to be used when the function is
called. This is mandated by the architecture software ABI."
 
K

Kenny McCormack

in comp.lang.c: .... ....
But I don't understand your question. You post one code sample which
you state if from glib source, then ask is the glib practice is
preferable. Preferable to what alternative?

I think that he was using "preferable" when he meant "desirable".

Give the guy a break!
 
K

Keith Thompson

Spoon said:
As far as I remember, on IA-64/Linux, object pointers are 64 bits wide
while function pointers are 128 bits wide.

No, all pointers are 64 bits wide (at least on the IA-64/Linux system
I use).
cf. http://www.gelato.unsw.edu.au/archives/linux-ia64/0201/2679.html

"On IA64 and PPC64 the function pointer does not reference the function
itself, instead it points to a function descriptor. The function
descriptor contains a pointer to the function code plus additional data
such as a pointer to the global data to be used when the function is
called. This is mandated by the architecture software ABI."

If a function pointer points to a descriptor, there's no reason for it
to be bigger than an object pointer.
 
W

WaterWalk

Kenny said:
I think that he was using "preferable" when he meant "desirable".

Give the guy a break!

Yes, I should have used "desirable" rather than "preferable". Sorry for
this misuse of word.

When I saw this code in glib, I was confused: Glib is a widely-used
library. It's code must(at least I think) be reviewed thoroughly. Yet
this cast I posted is undefined. I just don't understand why the glib
developers use such an extension, since it's not necessary, as Richart
Bos previously said.

Hope this clarifies my question. :)
 
O

Old Wolf

WaterWalk said:
When I saw this code in glib, I was confused: Glib is a widely-used
library. It's code must(at least I think) be reviewed thoroughly. Yet
this cast I posted is undefined. I just don't understand why the glib
developers use such an extension, since it's not necessary, as Richart
Bos previously said.

Well, all of the systems that Glib runs on, support this extension.

Probably what happened is that the Glib developers did not
realise, or did not care, that it was non-standard. Perhaps
you could post on a Glib mailing list; they might be able to
explain exactly why they chose this route.
 
K

Keith Thompson

WaterWalk said:
On 22 Nov 2006 07:03:15 -0800, "WaterWalk", who's native language
comp.lang.c: [...]
So the result is that a (void (*)(void)) is cast to (void*). However a
search of this group and c99 standard indicates that casting a
function pointer to a void pointer is undefined behavior. I wonder if
the glib practice is preferable. ...
But I don't understand your question. You post one code sample which
you state if from glib source, then ask is the glib practice is
preferable. Preferable to what alternative?
[...]
Yes, I should have used "desirable" rather than "preferable". Sorry for
this misuse of word.

When I saw this code in glib, I was confused: Glib is a widely-used
library. It's code must(at least I think) be reviewed thoroughly. Yet
this cast I posted is undefined. I just don't understand why the glib
developers use such an extension, since it's not necessary, as Richart
Bos previously said.

I suspect that GLib is not intended to be completely portable to all
possible conforming C implementations. As far as I know, *most* C
compilers do support conversions between function pointers and void*.
Possibly GLib is merely intended to be portable to just those
compilers. (The phrase "as far as I know" may be assumed to imply a
wealth of ignorance; there are plenty of C compilers I'm not familiar
with.)

But as you say, it probably wasn't necessary to use this particular
extension; GLib could have used, say, void (*)(void) as a generic
pointer-to-function type.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top