473,385 Members | 1,834 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Baffled by this ... (casting of function pointers)

How can this work ?

I have the following declarations in a header:

Header
=========
typedef void (*VFPTR)(void) ;
void FOO_Callback(void*, char*, char*, int, unsigned long, void*,void*);
int bar(int *, char *, VFPTR, void *);

Source
=========
In the C source code, I come accross this line:

bar(&id, name, FOO_Callback, (void *)handle);

This compiles without any problems when compiling as a C program. When
compiling as a C++ source (stricter type checking etc) - the compiler
(unsuprisingly) threw a wobbly. I had to add an explicit "C-style" cast
as ff:

bar(&id, name, (VOID_FUNC)FOO_Callback, (void *)handle);

and the compiler was happy once again.

BUT - wait a minute, HOW can a function (FOO_Callback) declared as a
function returning void and accepting several arguments, be "coerced"
into a function that accepts no arguments?

Here are my questions:

1). Ok it compiles - but does it make sense?
2). Are there any conditions under which one may coerce a function that
requires arguments into one not taking arguments?
3). What does it mean to call a function that expects arguments, with no
arguments - will it even work ?
I hope someone can shed somelight on this baffling piece of "sleight of
hand".

Nov 15 '05 #1
7 1831
On Fri, 26 Aug 2005 00:42:00 +0000 (UTC), Alfonso Morra
<sw***********@the-ring.com> wrote:
How can this work ?

I have the following declarations in a header:

Header
=========
typedef void (*VFPTR)(void) ;
void FOO_Callback(void*, char*, char*, int, unsigned long, void*,void*);
int bar(int *, char *, VFPTR, void *);

Source
=========
In the C source code, I come accross this line:

bar(&id, name, FOO_Callback, (void *)handle);
The cast on handle is superfluous if it is a pointer of any type.
Since the prototype for bar is known, any pointer type will be
implicitly converted void* as part of evaluating the arguments.

This compiles without any problems when compiling as a C program. When
Since you should have received a diagnostic on the third argument, you
may have discovered an error in your compiler. It is also possible
that you need to raise the warning level or disable some language
extension.
compiling as a C++ source (stricter type checking etc) - the compiler
(unsuprisingly) threw a wobbly. I had to add an explicit "C-style" cast
as ff:

bar(&id, name, (VOID_FUNC)FOO_Callback, (void *)handle);
I assume you meant (VFPTR) as your cast.

and the compiler was happy once again.

BUT - wait a minute, HOW can a function (FOO_Callback) declared as a
function returning void and accepting several arguments, be "coerced"
into a function that accepts no arguments?
A cast is capable of coercing quite a few things, as far as compiler
syntax checking goes. Whether the code will work after the cast is a
completely different issue. Since bar thinks the argument is pointer
to a function taking no arguments, that is how bar would call the
function. When FOO_Callback actually gets control, it will look for
the four arguments and you will invoke undefined behavior.

Here are my questions:

1). Ok it compiles - but does it make sense?
No.
2). Are there any conditions under which one may coerce a function that
requires arguments into one not taking arguments?
Only if you never call it. Possibly if you can guarantee the
function will not attempt to look at the arguments.
3). What does it mean to call a function that expects arguments, with no
arguments - will it even work ?
Undefined behavior.


I hope someone can shed somelight on this baffling piece of "sleight of
hand".


Sleight of hand implies some skill as a magician. This is just sloppy
code.
<<Remove the del for email>>
Nov 15 '05 #2
On Fri, 26 Aug 2005 00:42:00 +0000 (UTC), Alfonso Morra
<sw***********@the-ring.com> wrote in comp.lang.c:
How can this work ?

I have the following declarations in a header:

Header
=========
typedef void (*VFPTR)(void) ;
void FOO_Callback(void*, char*, char*, int, unsigned long, void*,void*);
int bar(int *, char *, VFPTR, void *);

Source
=========
In the C source code, I come accross this line:

bar(&id, name, FOO_Callback, (void *)handle);

This compiles without any problems when compiling as a C program. When
compiling as a C++ source (stricter type checking etc) - the compiler
(unsuprisingly) threw a wobbly. I had to add an explicit "C-style" cast
as ff:
The fact that it compiles as a C program indicates one of two things.
The first is that your compiler could be broken. The second, and more
likely, is that your are not operating your compiler in conforming
mode, and it is accepting this as some sort of compiler specific
non-standard extension.

The code is just as illegal in C as it is in C++. Without the cast, a
conforming compiler must issue a diagnostic.
bar(&id, name, (VOID_FUNC)FOO_Callback, (void *)handle);

and the compiler was happy once again.

BUT - wait a minute, HOW can a function (FOO_Callback) declared as a
function returning void and accepting several arguments, be "coerced"
into a function that accepts no arguments?
The C standard specifically allows a pointer to a function of one type
to be converted to a pointer to a function of another type, with a
suitable cast. If the result is later converted back to the original
pointer type, again by the appropriate cast, the reconverted pointer
is guaranteed to point to the original function. So with the cast, it
is perfectly legal in C and, even though it's off-topic here, in C++.
Without the cast it is illegal in both languages.
Here are my questions:

1). Ok it compiles - but does it make sense?
With the cast, yes.
2). Are there any conditions under which one may coerce a function that
requires arguments into one not taking arguments?
With the cast, yes.
3). What does it mean to call a function that expects arguments, with no
arguments - will it even work ?
If you call a function through a function pointer of the wrong type,
the behavior is undefined. As far as the language is concerned, there
is no longer a definition of "work" in existence once you produce
undefined behavior.
I hope someone can shed somelight on this baffling piece of "sleight of
hand".


There are times when it is useful to deal with generic pointers in C.
A pointer to any type of object can be converted to pointer to void
and back to a pointer of the original type, and will still point to
the original object.

But there is no conversion at all defined between pointers to
functions and any type of pointer to object, not even pointer to void.
Object and function pointers do not exist on the same planet, and
can't be mixed.

So it is quite common to use void(*func)(void) as a generic pointer to
function. As long as the pointer is converted back to the proper type
and called with the correct number and type of arguments, the behavior
is well-defined.

--
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/~a...FAQ-acllc.html
Nov 15 '05 #3


Alfonso Morra wrote:
How can this work ?

I have the following declarations in a header:

Header
=========
typedef void (*VFPTR)(void) ;
void FOO_Callback(void*, char*, char*, int, unsigned long, void*,void*);
int bar(int *, char *, VFPTR, void *);

Source
=========
In the C source code, I come accross this line:

bar(&id, name, FOO_Callback, (void *)handle);

This compiles without any problems when compiling as a C program. When
compiling as a C++ source (stricter type checking etc) - the compiler
(unsuprisingly) threw a wobbly. I had to add an explicit "C-style" cast
as ff:

bar(&id, name, (VOID_FUNC)FOO_Callback, (void *)handle);

and the compiler was happy once again.

BUT - wait a minute, HOW can a function (FOO_Callback) declared as a
function returning void and accepting several arguments, be "coerced"
into a function that accepts no arguments?

Here are my questions:

1). Ok it compiles - but does it make sense?
2). Are there any conditions under which one may coerce a function that
requires arguments into one not taking arguments?
3). What does it mean to call a function that expects arguments, with no
arguments - will it even work ?
I hope someone can shed somelight on this baffling piece of "sleight of
hand".

Anyone care to add a third view? - I'm none the wiser here since the two
responses I received contradict each other...

Nov 15 '05 #4
On Thu, 25 Aug 2005 20:43:33 -0700, Barry Schwarz wrote:
On Fri, 26 Aug 2005 00:42:00 +0000 (UTC), Alfonso Morra
<sw***********@the-ring.com> wrote:
How can this work ?

I have the following declarations in a header:

Header
=========
typedef void (*VFPTR)(void) ;
void FOO_Callback(void*, char*, char*, int, unsigned long, void*,void*);
int bar(int *, char *, VFPTR, void *);

Source
=========
In the C source code, I come accross this line:

bar(&id, name, FOO_Callback, (void *)handle);


The cast on handle is superfluous if it is a pointer of any type.
Since the prototype for bar is known, any pointer type will be
implicitly converted void* as part of evaluating the arguments.


Only pointers to unqualified object or imcomplete types can be converted
implicitly to void *. Function pointers can't nor can pointers with types
like const int * or indeed const void *. However this is a good thing and
attempts at conversions like these should be warned about so the code is
much better without the cast.

Lawrence
Nov 15 '05 #5
On Fri, 26 Aug 2005 09:22:10 +0000, Alfonso Morra wrote:


Alfonso Morra wrote:
How can this work ?

I have the following declarations in a header:

Header
=========
typedef void (*VFPTR)(void) ;
void FOO_Callback(void*, char*, char*, int, unsigned long, void*,void*);
int bar(int *, char *, VFPTR, void *);

Source
=========
In the C source code, I come accross this line:

bar(&id, name, FOO_Callback, (void *)handle);

This compiles without any problems when compiling as a C program. When
compiling as a C++ source (stricter type checking etc) - the compiler
(unsuprisingly) threw a wobbly. I had to add an explicit "C-style" cast
as ff:

bar(&id, name, (VOID_FUNC)FOO_Callback, (void *)handle);

and the compiler was happy once again.

BUT - wait a minute, HOW can a function (FOO_Callback) declared as a
function returning void and accepting several arguments, be "coerced"
into a function that accepts no arguments?
You can cast pointer types, but ultimately when you call a function the
arguments you call it with must be compatible with its definition.
Essentially that means if you cast a function pointer to a different
function pointer type you must cast it back again before calling the
function.
Here are my questions:

1). Ok it compiles - but does it make sense?
No, you're calling the function with the wrong number of arguments, this
has undefined behaviour i.e. the behaviour of your entire program ceases
to be well defined.
2). Are there any conditions under which one may coerce a function that
requires arguments into one not taking arguments?
Remember you are not "coercing" functions but pointers to functions. As
noted above you can do this but you must convert the pointer back again
before you call the function.
3). What does it mean
to call a function that expects arguments, with no arguments - will it
even work ?
Undefined behaviour means anything can happen. It might "work" to some
degree, it might fail completely, you get no guarantees either way.
I hope someone can shed somelight on this baffling piece of "sleight of
hand".

The code is simply broken.
Anyone care to add a third view? - I'm none the wiser here since the two
responses I received contradict each other...


How so?

Lawrence

Nov 15 '05 #6


Lawrence Kirby wrote:
On Fri, 26 Aug 2005 09:22:10 +0000, Alfonso Morra wrote:


Alfonso Morra wrote:

How can this work ?

I have the following declarations in a header:

Header
=========
typedef void (*VFPTR)(void) ;
void FOO_Callback(void*, char*, char*, int, unsigned long, void*,void*);
int bar(int *, char *, VFPTR, void *);

Source
=========
In the C source code, I come accross this line:

bar(&id, name, FOO_Callback, (void *)handle);

This compiles without any problems when compiling as a C program. When
compiling as a C++ source (stricter type checking etc) - the compiler
(unsuprisingly) threw a wobbly. I had to add an explicit "C-style" cast
as ff:

bar(&id, name, (VOID_FUNC)FOO_Callback, (void *)handle);

and the compiler was happy once again.

BUT - wait a minute, HOW can a function (FOO_Callback) declared as a
function returning void and accepting several arguments, be "coerced"
into a function that accepts no arguments?

You can cast pointer types, but ultimately when you call a function the
arguments you call it with must be compatible with its definition.
Essentially that means if you cast a function pointer to a different
function pointer type you must cast it back again before calling the
function.

Here are my questions:

1). Ok it compiles - but does it make sense?

No, you're calling the function with the wrong number of arguments, this
has undefined behaviour i.e. the behaviour of your entire program ceases
to be well defined.

2). Are there any conditions under which one may coerce a function that
requires arguments into one not taking arguments?

Remember you are not "coercing" functions but pointers to functions. As
noted above you can do this but you must convert the pointer back again
before you call the function.

3). What does it mean
to call a function that expects arguments, with no arguments - will it
even work ?

Undefined behaviour means anything can happen. It might "work" to some
degree, it might fail completely, you get no guarantees either way.

I hope someone can shed somelight on this baffling piece of "sleight of
hand".

The code is simply broken.

Anyone care to add a third view? - I'm none the wiser here since the two
responses I received contradict each other...

How so?

Lawrence


Thanks Lawrence, your posyt clarifies things up. BTW, I posted my
"request for disambiguation" before your last post (i.e. only Barry and
Jack had responded, and they each had a different P.O.V).

What you've said so far ties in with what Jack says - and it does stand
to reason if one pauses to think carefully at what is actually been done.

Nov 15 '05 #7
Alfonso Morra wrote:

Thanks Lawrence, your posyt clarifies things up. BTW, I posted my
"request for disambiguation" before your last post (i.e. only Barry and
Jack had responded, and they each had a different P.O.V).

What you've said so far ties in with what Jack says - and it does stand
to reason if one pauses to think carefully at what is actually been done.


Actually, all three posters (Barry, Jack and Lawrence) have told you the
same thing. They all stated that you must change the pointer back before
calling the function through it and that failing to do so invokes
undefined behaviour. Why would you think Barry said something different?

-- Denis

Nov 15 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: Ernesto | last post by:
Hi everybody: I have implemented a Pointer class template that uses reference counting to deallocate memory automatically. I have the following code using my Pointer: char* auxchar = new...
10
by: Dirk Vanhaute | last post by:
I have only small knowledge of c++, but I would like to compile the example in http://support.microsoft.com/kb/q246772/ HOWTO: Retrieve and Set the Default Printer in Windows I included "#include...
9
by: Simon | last post by:
Hi All, Is it possible to disallow implicit casting for an operand of a function written in C? i.e. void foo(int a) {..} short b; foo(b) // error without explicit cast
27
by: Rouben Rostamian | last post by:
I am reading the last chapter in Kernighan and Pike's "The Unix Programming Environment" where they describe their program "hoc" which, in effect, is a multifunction programmable calculator. In...
15
by: Eirik | last post by:
This is a little function I wrote, inspired by the thread "Urgent HELP! required for Caesar Cipher PLEASE" $ cat /home/keisar/bin/c/ymse/rot13.h char rot13(char character) { int changed;...
13
by: Kelvin Moss | last post by:
Hi group, In C++ it's undefined behavior if one tries to un-const the constness of a const variable with const_cast<>. I want to know if the same holds good in C too. E.g. const char *s =...
8
by: scroopy | last post by:
hi, why does the following produce an output of 64769 instead of 1 int main() { bool* pBool = new bool(false); unsigned short* pUS = (unsigned short*)pBool;
2
by: Noah Roberts | last post by:
I have a class, that inherits from a class that inherits virtually from another class. I have a breakdown occuring and it is not wrt the virtually inherited class but one of the other MIed pure...
8
by: lennin | last post by:
#define NULL 0 int main() { unsigned int p = NULL; /* Empty your mind */ if (p!=NULL) delete &p;
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.