473,320 Members | 2,098 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,320 software developers and data experts.

*generic* pointer to function(s)?

Hi everyone

I am interested in having multiple functions with different prototypes
and deciding, by setting a pointer, which of them to use later in the
program.

Eg:

int f1(void);
char* f2(int);
/* ... many more of these to choose from */

/* ? correct declaration of generic_ptr ? */

if (/*...*/)
generic_ptr = f1;
else
generic_ptr = f2;

generic_ptr(/* using correct args */)

How should I define generic_ptr? Is (void*) ok? It seems to work on my
machine, but I would like to know if this is standard/portable.

Thank you for any help

Juergen
Dec 3 '07 #1
7 3363
ju*********@yahoo.com wrote:
Hi everyone

I am interested in having multiple functions with different prototypes
and deciding, by setting a pointer, which of them to use later in the
program.

Eg:

int f1(void);
char* f2(int);
/* ... many more of these to choose from */

/* ? correct declaration of generic_ptr ? */

if (/*...*/)
generic_ptr = f1;
else
generic_ptr = f2;
This is not possible, but you can do something like

void (*generic_ptr)();
if (/*...*/)
generic_ptr = (void(*)()) f1;
else
generic_ptr = (void(*)()) f2;

Although I usually consider typedefs for pointer types to be
a Bad Thing, this is one of the exceptions where it seems to
me the readability can be improved a lot:

typedef void (*FuncPtr)();
FuncPtr generic_ptr;
if (/*...*/)
generic_ptr = (FuncPtr)f1;
else
generic_ptr = (FuncPtr)f2;
generic_ptr(/* using correct args */)
You can *almost* do this, but only if all of your functions
obey some rather strange restrictions:

- All of f1, f2, ... and generic_ptr must return the same
type, or all must be void

AND

- None of f1, f2, ... and generic_ptr can be a variadic
function, or all must be variadic and have the same number
and types of fixed arguments

AND

- If the argument types are omitted (as above), then all the
arguments to all of f1, f2, ... must be non-promotable, or
all of f1, f2, ... must be defined with the obsolescent
"K&R" syntax.

The problem is that the type of the pointer with which you
call a function must agree with the actual type of the function
that is called. The strange restrictions listed above allow you
to skirt the agreement rule just a little bit -- but there's
still no way you can use the same pointer expression to call a
function returning int *and* a function returning double, for
example.

An alternative is to cast at the point of call, which again
is clarified by the use of some typedefs:

typedef int (*IntOfVoid)(void);
typedef char* (*StrOfInt)(int);
if (/*...*/)
i = ((IntOfVoid)generic_ptr)();
else
s = ((StrOfInt)generic_ptr)(42);
How should I define generic_ptr? Is (void*) ok? It seems to work on my
machine, but I would like to know if this is standard/portable.
See above. No. Happenstance, and it's not.

If the functions f1, f2, ... really bear no resemblance to
each other you're pretty much doomed to casting -- but in such a
case it's hard to see why you'd want to use a single "generic"
pointer in the first place. If they are related in some way but
differ in details, it may be better to use wrapper functions.
For example, suppose all the functions return int values, all
take two int arguments, and some also take a third string argument.
You could do something like

int f1(int, int, char*);
int f2(int, int, char*);
int f3(int, int); /* only two arguments */

int wrapf3(int x, int y, char* unused) {
return f3(x, y);
}

typedef int (*FuncPtr)(int, int, char*);
FuncPtr fptr;

if (/*...*/)
fptr = f1;
else if (/*...*/)
fptr = f2;
else
fptr = wrapf3; /* note indirection */

printf ("%d\n", fptr(42, 29, "Zaphod Rulez!"));

This technique may appear limiting at first glance, but when
you start applying it to actual "families" of "broadly similar"
functions it works quite well.

--
Er*********@sun.com
Dec 3 '07 #2
Eric, Peter

Thank you for the stupendously informative replies.

J
Dec 3 '07 #3
ju*********@yahoo.com writes:
I am interested in having multiple functions with different prototypes
and deciding, by setting a pointer, which of them to use later in the
program.

Eg:

int f1(void);
char* f2(int);
/* ... many more of these to choose from */

/* ? correct declaration of generic_ptr ? */

if (/*...*/)
generic_ptr = f1;
else
generic_ptr = f2;

generic_ptr(/* using correct args */)

How should I define generic_ptr? Is (void*) ok? It seems to work on my
machine, but I would like to know if this is standard/portable.
void* is a generic object pointer type, in the sense that (1) you can
convert any object pointer to void* and back again, and get the
original pointer, and (2) such conversions can be done implicitly
(e.g., by a simple assignment rather than a cast).

There's no guarantee that converting a function pointer to or from
void* will give you anything meaningful. There is no generic function
pointer type in the sense of (2) above; conversions to and from
function pointer types must be explicit. But in the sense of (1),
*all* function pointer types are effectively generic; you can convert
a function pointer to any other function pointer type and back again
and get the same pointer. In effect, all function pointers "smell
alike", something that's not the case for object pointers.

But calling a function via a pointer of the wrong type invokes
undefined behavior.

Your best bet is probably to use something like ``void(*)(void)'',
(use a typedef) but you'll need to explicitly convert to or from this
type. Since there's no runtime representation of types (e.g., you
can't say ``if (typeof(x) == int)''), you'll need to use a switch
statement to select the proper type, and write each type of call
individually.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Dec 4 '07 #4
Walter Roberson wrote:
If I recall correctly, casting between a function pointer and an
object pointer (or the other way) is not banned, and that C
implementations are permitted to assign semantics to the result,
but the semantics are not specified in the C standards.
That's what "undefined" means.

Implementations are permitted to assign semantics
to the result of (1 / 0) also.

--
pete
Dec 4 '07 #5
pete <pf*****@mindspring.comwrites:
Walter Roberson wrote:
>If I recall correctly, casting between a function pointer and an
object pointer (or the other way) is not banned, and that C
implementations are permitted to assign semantics to the result,
but the semantics are not specified in the C standards.

That's what "undefined" means.
Yes, but the previous poster had speculated that such casts are
"banned". They aren't.
Implementations are permitted to assign semantics
to the result of (1 / 0) also.
True.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Dec 4 '07 #6
<ju*********@yahoo.comwrote in message
I am interested in having multiple functions with different prototypes
and deciding, by setting a pointer, which of them to use later in the
program.

Eg:

int f1(void);
char* f2(int);
/* ... many more of these to choose from */
Don't go down this route.
Building an argument list at runtime is one of the very few operations that
C will not allow you to do.
You can cast to and from void (*fptr)(void) s and any other type on almost
every architecture, but that avails you little if you are then going to
hardcode the calls. You might as well do the job properly and use a union.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Dec 4 '07 #7
Malcolm McLean wrote, On 04/12/07 22:06:
<ju*********@yahoo.comwrote in message
>I am interested in having multiple functions with different prototypes
and deciding, by setting a pointer, which of them to use later in the
program.

Eg:

int f1(void);
char* f2(int);
/* ... many more of these to choose from */
Don't go down this route.
Building an argument list at runtime is one of the very few operations
that C will not allow you to do.
True.
You can cast to and from void (*fptr)(void) s and any other type on
almost every architecture,
You can do it on *every* architecture that has a C compiler because the
C standard says you can do it.
but that avails you little if you are then
going to hardcode the calls. You might as well do the job properly and
use a union.
Whether a union buys you anything will depend on the exact situation.
--
Flash Gordon
Dec 5 '07 #8

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

Similar topics

7
by: Master of C++ | last post by:
Hello Folks, I have a programming dilemma with templates and "genericity". I can think of a few solutions, but I am not sure which one is the best in terms of genetic C++ style. Any suggestions...
3
by: Axter | last post by:
I'm wondering about the practical use of dynamic_cast in reusable or generic code. I'm currently working on a smart pointer that can be used on vector and other STL containers. See following...
6
by: aurgathor | last post by:
Howdy, How do I pass some function a generic comparison function? I figured out one non-generic case, but since this code got parameter declarations in two places, it's obviously not generic....
1
by: Albert | last post by:
Hello all, I've got several questions and I'm sure you'll find them easy to answer, but sadly I don't know the answers though: What do people mean by generic pointers Why is a pointer to void...
11
by: redefined.horizons | last post by:
First, I would thank all of those that took the time to answer my question about creating an array based on a numeric value stored in a variable. I realize after reading the responses and doing...
3
by: markww | last post by:
Hi, I have a wrapper around some 3rd party database library function. The pseudo code looks like the following - it is meant to open a table in a database, extract values from a table, then copy...
3
by: Frederick Gotham | last post by:
For objects, we have "void*" as the generic pointer type. For instance: enum ParamType { Int, Double }; void Func(void *const p,ParamType const pt) { switch (pt) { case Int: *(int*)p = 42;...
1
by: interX | last post by:
Hi I'm new in VC++ and have a question to generics. I have a generic class, which contains an array of the generic type. This array I can pin and then I would like to get an unmanaged pointer to...
32
by: copx | last post by:
Why doesn't the C standard include generic function pointers? I use function pointers a lot and the lack of generic ones is not so cool. There is a common compiler extension (supported by GCC...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

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.