function pointer with generic argument type - c

for knowledge sake, I would like to know if something like this is possible:
2 function:
static int func1(int *a, int b){
...
}
static int func2(double *a, int b){
...
}
I would like to declare a function pointer and point it to one of these function. However the arguments of these functions are of different type. So I tried:
static int (*func_ptr)(void *arg1, int arg2);
static void *Argument1;
static int Argument2=5;
int main(){
double arg1_d;;
int arg1_i;
...
if(want_func2){
Argument1=(double *) &arg1_d;
func_ptr=func2;
run(func_ptr);
}
else{
Argument1=(int *) &arg1_i;
func_ptr=func1;
run(func_ptr);
}
return 0;
}
static int run(int *(function)(void *,int )){
function(Argument1,Argument2);
}
However, when compiling I get the warning:
warning: assignment from incompatible pointer type
when
func_ptr=func2;
func_ptr=func1;
Is there anyway to create a function pointer with a generic type argument?

You are on the right track. But, in order to achieve what you want, your functions should have a void* parameter and cast it internally to int or double.

No. You need the if...else to use such a thing correctly anyway, so just store separate function pointers and use the correct pointer in each piece of code.

Related

Which type to use for an arbitrary function pointer in C?

In short, my question is: does the C standard allow for an arbitrary function pointer type similar to void * being an arbitrary data pointer type?
It is common to define call-back function types with a void * parameter to pass on an arbitrary data package whose format is known to the call-back function, but not to the caller.
For example:
typedef void (* EventFunctionType)(void *data);
void RegisterEventFunction(EventFunctionType function, void *data);
An "EventFunction" can then be registered with a data pointer which will be passed to the function when it is called.
Now suppose we want to pass a function pointer to the call-back. The function could have any prototype which would be known to the specific call-back function, just like the arbitrary data structure above.
A void * cannot hold a function pointer, so which type could be used?
Note: An obvious solution to this problem would be to wrap the function pointer in a data structure with the correct function pointer type, but the question is if the function pointer could be passed on directly in a generic form which the call-back could then cast to a pointer with the correct prototype?
There are no function pointer type that works the same as/similar to to void-pointer.
But function pointers has another characteristic that can be used. It's already referenced in the answer linked in this question:
In the C11 draft standard N1570, 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.
This mean that you can use any function pointer type as your "arbitrary function pointer type". It doesn't matter as long as you know how to get back to the real/original type (i.e. know the original type so that you can cast correctly).
For instance:
typedef void (*func_ptr_void)(void);
and then use func_ptr_void as your "arbitrary function pointer type".
But notice that unlike conversion between void* and other object pointer types, the conversion between function pointers will always require an explicit cast. The code example below shows this difference:
#include <stdio.h>
typedef void (*func_ptr_void)(void);
typedef int (*f_int)(int);
int bar(int n)
{
return n * n;
}
int test(func_ptr_void f, int y)
{
f_int fc = (f_int)f; // Explicit cast
return fc(y);
}
int foo(void* p)
{
int* pi = p; // Explicit cast not needed
return *pi;
}
int main(void)
{
int x = 42;
void* pv = &x; // Explicit cast not needed
printf("%d \n", foo(pv));
func_ptr_void fpv = (func_ptr_void)bar; // Explicit cast
printf("%d \n", test(fpv, 5));
return 0;
}
does the C standard allow for an arbitrary function pointer type similar to void * being an arbitrary data pointer type?
No. Two function pointers are only compatible if their return types and parameters (including qualifiers) match.
However, pointer conversions between any two function pointers by means of a cast are well-defined (6.3.2.3/8) as long as you don't invoke the function through the wrong pointer type. This means that you can use any function pointer type as a "generic function pointer" as long as you keep track of what function that pointer actually points at. Such as using an extra enum for that purpose.
Generally when using function pointers, we don't do that however, but instead define a common interface. For example like the callbacks to bsearch/qsort which use the form int (*)(const void*, const void*).
Here's an example of "keep track of type using enum", which is not something I particularly recommend but otherwise perfectly well-defined:
#include <stdio.h>
static int intfunc (int x)
{
printf("%d\n", x);
return x;
}
static double doublefunc (double x)
{
printf("%f\n", x);
return x;
}
typedef enum
{
INTFUNC,
DOUBLEFUNC
} functype_t;
typedef void generic_func_t (void);
typedef int int_func_t (int);
typedef int double_func_t (double);
typedef struct
{
generic_func_t* fptr;
functype_t type;
} func_t;
void func_call (const func_t* f)
{
switch(f->type)
{
case INTFUNC: ((int_func_t*)f->fptr ) (1); break;
case DOUBLEFUNC: ((double_func_t*)f->fptr) (1.0); break;
}
}
int main (void)
{
func_t f1 = { (generic_func_t*)intfunc, INTFUNC };
func_t f2 = { (generic_func_t*)doublefunc, DOUBLEFUNC };
func_call(&f1);
func_call(&f2);
}
That's "old school" C, but it is not recommended since it is clunky, brittle and not really type safe. In modern C programming we wouldn't write that kind of code however, but replace that whole mess with something like this:
#include <stdio.h>
static int intfunc (int x)
{
printf("%d\n", x);
return x;
}
static double doublefunc (double x)
{
printf("%f\n", x);
return x;
}
#define func_call(obj) \
_Generic((obj), \
int: intfunc, \
double: doublefunc) (obj) \
int main (void)
{
func_call(1);
func_call(1.0);
}

How to fix "conflicting types" for a function and its declaration?

I want to pass a two-dimensional char array to a function but don't know how to declare the function before the main(). The function compiles and works well before I declare it. But after I declare it, I encounter compiling issues.
I'm using EMACS on MacBook pro. The compiler is gcc.I tried to declare my function print string various ways including
void printstring(int, int,char **);
or
void printstring(int, int,char *);
But none of them work. My Full codes are:
#include<stdio.h>
#include<stdlib.h>
void printstring(int, int,char **);
int main(){
char word[3][6]= {"hello","world","I"};
printstring(3,6,word);
return 0;
}
void printstring(int n, int m, char (*w)[m]){
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
I expected that there is no compiling error but I got one error and one warning. Details can be found below:
test.c: In function 'main':
test.c:9:19: warning: passing argument 3 of 'printstring' from incompatible pointer type [-Wincompatible-pointer-types]
printstring(3,6,word);
^~~~
test.c:5:6: note: expected 'char **' but argument is of type 'char (*)[6]'
void printstring(int, int,char **);
^~~~~~~~~~~
test.c: At top level:
test.c:13:6: error: conflicting types for 'printstring'
void printstring(int n, int m, char (*w)[m]){
^~~~~~~~~~~
test.c:5:6: note: previous declaration of 'printstring' was here
void printstring(int, int,char **);
^~~~~~~~~~~
the problem is that you're using a variable length array. The last argument (the list of strings) depends on the second argument (m). And char ** is not suitable, as it's just a pointer on pointers. So the max dimension of the strings would be lost when iterating on the 2D array.
Use a standard forward declaration, copying exactly the real declaration if you don't want to put the function before the main one.
void printstring(int n, int m, char (*w)[m]);
int main(){
char word[3][6]= {"hello","world","I"};
printstring(3,6,word);
return 0;
}
void printstring(int n, int m, char (*w)[m]){
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
If you have read-only strings, I suggest that you use a standard array of constant pointers instead:
void printstring(int n, const char *w[]);
int main(){
const char *word[] = {"hello","world","I"};
printstring(3,word);
return 0;
}
void printstring(int n, const char *w[])
{
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
note that
printstring(3,word);
can be replaced by
printstring(sizeof(word)/sizeof(word[0]),word);
before array decays to pointer (that autocomputes the number of strings)
If you want to maintain a name free declaration for whatever reason, you can use the * notation (reserved to function prototype scope) for the variably modified type
void printstring(int, int,char (*)[*]);
Still a VLA, and in fact, exactly equivalent to the notation that uses m. Though, ostensibly, it may convey intent not as clearly as using m in the forward declaration.
The following should just work:
void printstring(int n, int m, char (*w)[m]);
The function prototype and definition should be kept identical, except maybe for certain qualifiers such as const and default arguments in C++.
char** cannot be used to point at 2D arrays, it can only be used to point at the first element of a 1D array of char*, which is something else.
Your compiler error is from having non-matching declaration and definition. Correct code:
void printstring(int n, int m, char w[n][m]);
...
void printstring(int n, int m, char w[n][m]){
...
}
Alternatively, you can write void printstring(int n, int m, char (*w)[m]) and it is completely equivalent. But that is just harder to read, so why would you?

Function Returning Itself

Is it possible to declare some function type func_t which returns that type, func_t?
In other words, is it possible for a function to return itself?
// func_t is declared as some sort of function pointer
func_t foo(void *arg)
{
return &foo;
}
Or would I have to use void * and typecasting?
No, you cannot declare recursive function types in C. Except inside a structure (or an union), it's not possible to declare a recursive type in C.
Now for the void * solution, void * is only guaranteed to hold pointers to objects and not pointers to functions. Being able to convert function pointers and void * is available only as an extension.
A possible solution with structs:
struct func_wrap
{
struct func_wrap (*func)(void);
};
struct func_wrap func_test(void)
{
struct func_wrap self;
self.func = func_test;
return self;
}
Compiling with gcc -Wall gave no warnings, but I'm not sure if this is 100% portable.
You can't cast function pointers to void* (they can be different sizes), but that's not a problem since we can cast to another function pointer type and cast it back to get the original value.
typedef void (*fun2)();
typedef fun2 (*fun1)();
fun2 rec_fun()
{
puts("Called a function");
return (fun2)rec_fun;
}
// later in code...
fun1 fp = (fun1)((fun1)rec_fun())();
fp();
Output:
Called a function
Called a function
Called a function
In other words, is it possible for a function to return itself?
It depends on what you mean by "itself"; if you mean a pointer to itself then the answer is yes! While it is not possible for a function to return its type a function can return a pointer to itself and this pointer can then be converted to the appropriate type before calling.
The details are explained in the question comp.lang.c faq: Function that can return a pointer to a function of the same type.
Check my answer for details.
Assume the function definition
T f(void)
{
return &f;
}
f() returns a value of type T, but the type of the expression &f is "pointer to function returning T". It doesn't matter what T is, the expression &f will always be of a different, incompatible type T (*)(void). Even if T is a pointer-to-function type such as Q (*)(void), the expression &f will wind up being "pointer-to-function-returning-pointer-to-function", or Q (*(*)(void))(void).
If T is an integral type that's large enough to hold a function pointer value and conversion from T (*)(void) to T and back to T (*)(void) is meaningful on your platform, you might be able to get away with something like
T f(void)
{
return (T) &f;
}
but I can think of at least a couple of situations where that won't work at all. And honestly, its utility would be extremely limited compared to using something like a lookup table.
C just wasn't designed to treat functions like any other data item, and pointers to functions aren't interchangeable with pointers to object types.
what about something like this:
typedef void* (*takesDoubleReturnsVoidPtr)(double);
void* functionB(double d)
{
printf("here is a function %f",d);
return NULL;
}
takesDoubleReturnsVoidPtr functionA()
{
return functionB;
}
int main(int argc, const char * argv[])
{
takesDoubleReturnsVoidPtr func = functionA();
func(56.7);
return 0;
}
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
typedef void *(*fptr)(int *);
void *start (int *);
void *stop (int *);
void *start (int *a) {
printf("%s\n", __func__);
return stop(a);
}
void *stop (int *a) {
printf("%s\n", __func__);
return start(a);
}
int main (void) {
int a = 10;
fptr f = start;
f(&a);
return 0;
}
It is not possible for a function to return itself by value. However it is possible itself to return by a pointer.
C allows to define function types that take undefined number of parameters and those those types are compatible with function types that take defined parameters.
For example:
typedef void fun_t();
void foo(int);
fun_t *fun = foo; // types are fine
Therefore the following function would work.
void fun(void (**ptr)()) {
*ptr = &fun;
}
And below you can find the exemplary usage:
#include <stdio.h>
void fun(void (**ptr)()) {
puts("fun() called");
*ptr = &fun;
}
int main() {
void (*fp)();
fun(&fp); /* call fun directly */
fp(&fp); /* call fun indirectly */
return 0;
}
The code compiles in pedantic mode with no warnings for C89 standard.
It produces the expected output:
fun() called
fun() called
There's a way, you just try this:
typedef void *(*FuncPtr)();
void *f() { return f; }
int main() {
FuncPtr f1 = f();
FuncPtr f2 = f1();
FuncPtr f3 = f2();
return 0;
}
If you were using C++, you could create a State object type (presuming the state machine example usage) wherein you declare an operator() that returns a State object type by reference or pointer. You can then define each state as a derived class of State that returns each appropriate other derived types from its implementation of operator().

const array const {}

So you can do this:
void foo(const int * const pIntArray, const unsigned int size);
Which says that the pointer coming is read-only and the integer's it is pointing to are read-only.
You can access this inside the function like so:
blah = pIntArray[0]
You can also do the following declaration:
void foo(const int intArray[], const unsigned int size);
It is pretty much the same but you could do this:
intArray = &intArray[1];
Can I write:
void foo(const int const intArray[], const unsigned int size);
Is that correct?
No, your last variant is not correct. What you are trying to do is achieved in C99 by the following new syntax
void foo(const int intArray[const], const unsigned int size);
which is equivalent to
void foo(const int *const intArray, const unsigned int size);
That [const] syntax is specific to C99. It is not valid in C89/90.
Keep in mind that some people consider top-level cv-qualifiers on function parameters "useless", since they qualify a copy of the actual argument. I don't consider them useless at all, but personally I don't encounter too many reasons to use them in real life.
Use cdecl. It gives an error on the second entry. The first only clearly suggests that the second const refers to the *.
In C/C++, you cannot pass an entire array as an argument to a function.
You can,
however, pass to the function a pointer to an array by specifying the array's name
without an index.
(E.g)
This program fragment passes the address of i to func1() :
int main(void)
{
int i[10];
func1(i);
.
.
.
}
To receive i, a function called func1() can be defined as
void func1(int x[]) /* unsized array */
{
.
.
}
or
void func1(int *x) /* pointer */
{
.
.
}
or
void func1(int x[10]) /* sized array */
{
.
.
}
source : THE COMPLETE REFERENCE - HERBERT.

C: Passing a function pointer in a function it is passed to

I'm trying to write a mapping function that takes a function pointer, and passes it to another function, but gcc is yelling at me.
Here is an idea of what I'm trying to do.
void map(T thing, void apply(int a, int b, void *cl), void *cl);
void function(T thing, void apply(int a, int b, void *cl), void * cl)
{
for(int i = 0; i < 10; i++)
{
map(thing, apply, cl);
}
}
gcc's complaint:
warning: passing argument 2 of 'map' from incompatible pointer type
Any ideas?
In order to help with this problem we'd need to see the declaration / signature of the map function. Almost certainly there is a slight difference in the function signature. The easiest way to resolve this is to typedef out a function pointer type and use it in both functions.
typedef void (*apply)(int,int,void*);
You can't pass functions around. You need to pass pointers to functions instead.
void map(T thing, void (*apply)(int a, int b, void *cl), void *cl);
void function(T thing, void (*apply)(int a, int b, void *cl), void * cl)
{
/* ... */
map(thing, apply, cl);
/* .... */
}
It's just complaining that the function pointer type expected by map's second argument is different from that of apply. If you either change that type, or (if safe) cast, then it'll be fine.
It works for me with gcc 4.3.3 and -Wall.
While I think all versions of C that ever existed rewrote function "value" parameters to be pointers, you could use a more traditional declaration:
void function(T thing, void (*f)(int a, int b, void *cl), void * cl)
But, like I said, your example works fine for me, unchanged except for typedef int T, and map(1, ...)

Resources