By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,778 Members | 1,957 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,778 IT Pros & Developers. It's quick & easy.

typedef Used to Cast Function Pointers

P: n/a
Is is possible to use typedefs to cast function pointers? I think I
saw this in the WINGs src; grep for '(hashFunc)'. So far, trying to
use a typedef to cast function pointers so that a return value of
float is changed to float seems not to work; I belive it was like
this:

typedef int (*foo) (int);

function_ptr_bar = (foo)function_that_returns_float;
Nov 13 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
Barbrawl McBribe wrote:
Is is possible to use typedefs to cast function pointers?
Only a cast expression can be used to cast.
I think I
saw this in the WINGs src; grep for '(hashFunc)'. So far, trying to
use a typedef to cast function pointers so that a return value of
float is changed to float seems not to work; I belive it was like
this:

typedef int (*foo) (int);
This declares foo as an alias for type "pointer to function taking 1
argument of type int and returning int".

function_ptr_bar = (foo)function_that_returns_float;


This uses a cast expression to convert from one type to another. I don't
believe you can safely call the function through the resulting pointer
unless it is first cast back to the correct type.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Nov 13 '05 #2

P: n/a
fi*******@thelinuxlink.net (Barbrawl McBribe) writes:
Is is possible to use typedefs to cast function pointers? I think I
saw this in the WINGs src; grep for '(hashFunc)'. So far, trying to
use a typedef to cast function pointers so that a return value of
float is changed to float seems not to work; I belive it was like
this:

typedef int (*foo) (int);

function_ptr_bar = (foo)function_that_returns_float;


I presume you mean "so that a return value of float is changed to
int".

Why would you want to do this? You can probably make it work, but
it's extremely unsafe and non-portable. Basically, you're trying to
lie to the compiler. At best, you'll call function_that_returns_float()
and treat its result as an int (not a numeric conversion, but a
reinterpretation of the bits). At worst, the calling conventions will
differ, and arbitrarily bad things will happen, from getting
meaningless garbage to crashing your program.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
(Note new e-mail address)
Nov 13 '05 #3

P: n/a


Keith Thompson wrote:
fi*******@thelinuxlink.net (Barbrawl McBribe) writes:
Is is possible to use typedefs to cast function pointers? I think I
saw this in the WINGs src; grep for '(hashFunc)'. So far, trying to
use a typedef to cast function pointers so that a return value of
float is changed to float seems not to work; I belive it was like
this:

typedef int (*foo) (int);

function_ptr_bar = (foo)function_that_returns_float;

I presume you mean "so that a return value of float is changed to
int".

Why would you want to do this? You can probably make it work, but
it's extremely unsafe and non-portable. Basically, you're trying to
lie to the compiler. At best, you'll call function_that_returns_float()
and treat its result as an int (not a numeric conversion, but a
reinterpretation of the bits). At worst, the calling conventions will
differ, and arbitrarily bad things will happen, from getting
meaningless garbage to crashing your program.


The Standard explicitly calls it Undefined Behavior.

From 6.3.2.3.8
"A pointer to a function of one type may be converted to
a pointer to a function of another type and back again;
the result shall compare equal to the original pointer.
If a converted pointer is used to call a function whose
type is not compatible with the pointed-to type, the
behavior is undefined."
--
Al Bowers
Tampa, Fl USA
mailto: xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

Nov 13 '05 #4

P: n/a
Al Bowers wrote:

The Standard explicitly calls it Undefined Behavior.

From 6.3.2.3.8
"A pointer to a function of one type may be converted to
a pointer to a function of another type and back again;
the result shall compare equal to the original pointer.
If a converted pointer is used to call a function whose
type is not compatible with the pointed-to type, the
behavior is undefined."


Question: In what ways could the function types be different, and still
be compatible? I'm guessing it's safe if the conversion adds const
and/or volatile qualifiers to some parameters. Could you replace a void*
parameter with a char* parameter? A signed integer with an unsigned
integer? What if the real function returns a value, but the pointer it's
called through is to a void function type?

I have my suspicions about the answers to these questions, but I'd like
to know if I'm wrong.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Nov 13 '05 #5

P: n/a
Kevin Goodsell wrote:

Al Bowers wrote:

The Standard explicitly calls it Undefined Behavior.

From 6.3.2.3.8
"A pointer to a function of one type may be converted to
a pointer to a function of another type and back again;
the result shall compare equal to the original pointer.
If a converted pointer is used to call a function whose
type is not compatible with the pointed-to type, the
behavior is undefined."
Question: In what ways could the function types be different, and still
be compatible? I'm guessing it's safe if the conversion adds const
and/or volatile qualifiers to some parameters. Could you replace a void*
parameter with a char* parameter? A signed integer with an unsigned
integer? What if the real function returns a value, but the pointer it's
called through is to a void function type?

I have my suspicions about the answers to these questions, but I'd like
to know if I'm wrong.


On the level of the source code being considered correct, they cannot be
different.

On the level of executing undefined behavior in a not-pernicious
manner, whenever nothing happens that would cause execution to halt - like
when the shape of the parameters are the same. You could mix up
ints, longs and pointers on some architectures.

But it's still wrong :)

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

--
Les Cargill
Nov 13 '05 #6

P: n/a
Keith Thompson <ks***@mib.org> wrote in message news:<ln************@nuthaus.mib.org>...
fi*******@thelinuxlink.net (Barbrawl McBribe) writes:
Is is possible to use typedefs to cast function pointers? I think I
saw this in the WINGs src; grep for '(hashFunc)'. So far, trying to
use a typedef to cast function pointers so that a return value of
float is changed to float seems not to work; I belive it was like
this:

typedef int (*foo) (int);

function_ptr_bar = (foo)function_that_returns_float;
I presume you mean "so that a return value of float is changed to
int".


Yes. This is just messing around; I deem it has no practical
application.

Why would you want to do this?
It's a CS thing... Personally, I just want to try what I can, and I
will learn from even stupid sh*t. Remember, as Carl Sagan said, that
fundamental science can be a prerequisite for applied science.

You can probably make it work, but it's extremely unsafe and non-portable.
Definitely...

Basically, you're trying to lie to the compiler.
That's a clever way of saying it.

At best, you'll call function_that_returns_float() and treat its result as an int (not a numeric conversion, but a
reinterpretation of the bits). At worst, the calling conventions will
differ, and arbitrarily bad things will happen, from getting
meaningless garbage to crashing your program.


Well, the casts in the WINGs source are casting to what the function
*was* in the first place, if you see what I mean (as in from a return
value of void * to void * and likewise for the arguments). I
eliminated them, recompiled, and all was well. I can conclude
reasonably that they are there for clarity.
Nov 14 '05 #7

P: n/a
On Sun, 07 Dec 2003 22:39:01 GMT, Kevin Goodsell
<us*********************@neverbox.com> wrote:
Al Bowers wrote:

The Standard explicitly calls it Undefined Behavior.

From 6.3.2.3.8
"A pointer to a function of one type may be converted to
a pointer to a function of another type and back again;
the result shall compare equal to the original pointer.
If a converted pointer is used to call a function whose
type is not compatible with the pointed-to type, the
behavior is undefined."


Question: In what ways could the function types be different, and still
be compatible? I'm guessing it's safe if the conversion adds const
and/or volatile qualifiers to some parameters. Could you replace a void*
parameter with a char* parameter? A signed integer with an unsigned
integer? What if the real function returns a value, but the pointer it's
called through is to a void function type?

Two *prototyped* function types are compatible (only) if corresponding
parameters are compatible ignoring top-level qualification and after
"adjustment" to pointer of (declared) array or function parameters,
and both or neither end with ellipsis (variadic). void* and char* are
not compatible according to the type rules, although they are required
to have the same representation and so substituting them will work in
practice unless the implementation is odd (or perverse) enough to pass
them differently, and the same for corresponding signed and unsigned
integers. Including plain/signed/unsigned char, and pointers thereto.

An incomplete or "forward declared" struct or union is compatible with
the completed type, and (nearly) identically declared such types or
enums in different t.u.s are compatible although formally they are not
the same type. An enum is compatible with an implementation-defined
integer type, usually int. Array of unspecified (or in C99 VLA) bound
is compatible (at compile time) with array of fixed bound. I think
that's all the freedom you officially have.

The more complicated cases are compatibility between or with
unprototyped function types, e.g.:
int foo (int x, double y);
int foo (x, y) short x; float y; { blah blah }
are compatible, and a pointer to unspecified-args function:
int (*ptr)() = foo;
can be silently converted from any function pointer, but can correctly
be used to call only a function with no arguments (and returning int).
For unprototyped definitions, the void*-char* and signed-unsigned
cases are permitted in 6.5.2.2, which is more detailed than 6.3.3.8.

Both prototyped and unprototyped declarations (and definitions) of a
function do define the return type, and (so) function types with
different return types are never compatible.
- David.Thompson1 at worldnet.att.net
Nov 14 '05 #8

P: n/a
fi*******@thelinuxlink.net (Barbrawl McBribe) writes:
Keith Thompson <ks***@mib.org> wrote in message
news:<ln************@nuthaus.mib.org>...

[...]
At best, you'll call function_that_returns_float() and treat its
result as an int (not a numeric conversion, but a reinterpretation
of the bits). At worst, the calling conventions will differ, and
arbitrarily bad things will happen, from getting meaningless
garbage to crashing your program.


Well, the casts in the WINGs source are casting to what the function
*was* in the first place, if you see what I mean (as in from a return
value of void * to void * and likewise for the arguments). I
eliminated them, recompiled, and all was well. I can conclude
reasonably that they are there for clarity.


Hmm. I don't know what WINGs might be, but simply casting a function
to its own type isn't going to do anything for clarity. On the
contrary, it's confusing and error-prone. Rather than letting the
compiler verify the function type, the cast forces the compiler to
assume that it's of the right type and inhibits error checks.

*Unless* it's casting function pointers to their proper types. I can
imagine a program keeping function pointers of various types in a data
structure, where each element stores a function pointer (cast to some
generic function pointer type) and an indication of the function's
actual type. A calling routine would then cast the function pointer
back to its original type. Something like that might be used in an
interpreter, for example.

It's something you might consider if you *really* know what you're
doing.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
(Note new e-mail address)
Nov 14 '05 #9

P: n/a
On Fri, 12 Dec 2003 22:04:55 GMT, I wrote, and apparently slipped at
least one cog while doing so:
<snip>
The more complicated cases are compatibility between or with
unprototyped function types, e.g.:
int foo (int x, double y);
int foo (x, y) short x; float y; { blah blah }
are compatible, and a pointer to unspecified-args function:
int (*ptr)() = foo;
can be silently converted from any function pointer, but can correctly
be used to call only a function with no arguments (and returning int).


Of course it can be used to call any oldstyle definition, or one with
prototyped parameter types not altered by the default promotions and
not variadic. But (in either case) they do have to return int.

- David.Thompson1 at worldnet.att.net
Nov 14 '05 #10

P: n/a
Keith Thompson <ks***@mib.org> wrote in message news:<ln************@nuthaus.mib.org>...
fi*******@thelinuxlink.net (Barbrawl McBribe) writes:
Keith Thompson <ks***@mib.org> wrote in message
news:<ln************@nuthaus.mib.org>... [...]
At best, you'll call function_that_returns_float() and treat its
result as an int (not a numeric conversion, but a reinterpretation
of the bits). At worst, the calling conventions will differ, and
arbitrarily bad things will happen, from getting meaningless
garbage to crashing your program.


Well, the casts in the WINGs source are casting to what the function
*was* in the first place, if you see what I mean (as in from a return
value of void * to void * and likewise for the arguments). I
eliminated them, recompiled, and all was well. I can conclude
reasonably that they are there for clarity.


Hmm. I don't know what WINGs might be


If you are familiar with the X Window System, it's a toolkit for the
same associated w/ the WindowMaker window manager.

but simply casting a function to its own type isn't going to do anything for clarity. On the
contrary, it's confusing and error-prone. Rather than letting the
compiler verify the function type, the cast forces the compiler to
assume that it's of the right type and inhibits error checks.
That makes sense.

*Unless* it's casting function pointers to their proper types. I can
imagine a program keeping function pointers of various types in a data
structure, where each element stores a function pointer (cast to some
generic function pointer type) and an indication of the function's
actual type. A calling routine would then cast the function pointer
back to its original type. Something like that might be used in an
interpreter, for example.
Eh?? Well, this is for hash table utility functions in the graphics
toolkit.
It's something you might consider if you *really* know what you're
doing.


Seems risky and evidently a lot of the behavior is undefined.
Nov 14 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.