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().
Related
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);
}
Following code works fine, however I was wondering if this is valid use of rule that void* is compatible with any other pointer
#include <stdio.h>
typedef struct {
int foo;
} SomeStruct_t;
typedef void(*SomeFunction_t)(void* ptr);
void bar(SomeStruct_t* str) {
printf("%d\n", str->foo);
}
void teddy(void* anyPtr) {
SomeStruct_t* str = (SomeStruct_t*)anyPtr;
printf("%d\n", str->foo);
}
int main()
{
SomeFunction_t functPtr = (SomeFunction_t)bar;
SomeStruct_t data = {.foo = 33};
functPtr(&data);
functPtr = teddy;
functPtr(&data);
return 0;
}
Question is, should I use bar or teddy variant? I prefer bar but I'm not sure if for some corner cases this might lead to hard to detect problem.
This is not valid:
SomeFunction_t functPtr = (SomeFunction_t)bar;
Because you're casing a function pointer of type void (*)(SomeStruct_t*) to type void (*)(void*) and subsequently calling it though the casted type. The function pointer types are not compatible because the parameters are not compatible. This triggers undefined behavior.
While a SomeStruct_t * can be converted to a void *, that conversion can't happen because the casted function pointer prevents it. There's no guarantee that SomeStruct_t * and void * have the same representation.
Using the function teddy which matches the function pointer type is safe. Also, you don't need to cast the parameter to SomeStruct_t * inside the function because conversions to/from void * don't require one in most cases.
I worte a test program to understand callback functions and function pointers.The program is given below.
My question is while assigning
cb_display = (void*)display_struct;
I have to cast the function to a void*. Why is this required even when the return type of function is void?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int a;
char b[16];
}myst_t;
void (*cb_display)(void*);
void display_struct(myst_t *st){
fprintf(stdout, "a -> %d b -> %s \n",st->a,st->b);
}
int main()
{
myst_t myst;
myst.a = 789432;
strncpy(myst.b,"helloabcd",9);
cb_display = (void*)display_struct;
cb_display(&myst);
return 0;
}
cb_display = (void*)display_struct;
is actually also not valid in C. Don't do it. You cannot assign a void * to a function pointer.
To fix your issue declare your function pointer as:
void (*cb_display)();
It means it matches a function that return no value and takes an unspecified number of parameters. You then don't need any cast. Also please note as it was pointed by Olaf in the comments that a function declarator with () while valid is an obsolescent C feature.
Of course if you will only pass functions like display_struct with a myst_t * parameter, you can also declare cb_display as: void (*cb_display)(myst_t *);
Changing void (cb_display)(void);
To typedef void (cb_display)(void);
May work.
As I know, I can define a function type:
typedef void (fn)(void);
and I can also define a function pointer type:
typedef void (*pfn)(void);
There are 2 functions. The first function's parameter type is a function, and the other is a function pointer:
void a(fn fn1)
{
fn1();
}
void b(pfn fn1)
{
fn1();
}
I implement a function callback:
void callback(void)
{
printf("hello\n");
}
and pass it as the argument to a and b:
int main(void) {
a(callback);
b(callback);
return 0;
}
Both a and b work well, and print "hello".
So I want to know what is the difference between defining a function type and a function pointer type? or actually, they are same?
Function types are treated as the corresponding function pointer type in argument lists.
There are basically two practical applications of (non-pointer) function types:
Avoiding the function pointer syntax, if you find it too baroque.
int apply(int (*f)(int), int x) {
return f(x);
}
int apply(int f(int), int x) {
return f(x);
}
Declaring multiple functions of the same type.
int add(int, int);
int subtract(int, int);
int multiply(int, int);
int divide(int, int);
typedef int arithmetic(int, int);
arithmetic add, subtract, multiply, divide;
The latter can be extremely useful to avoid repetition. Note however that function types don’t let you use const to prevent the pointer from being reassigned. So this compiles just fine:
#include <stdio.h>
int pred(int const i) { return i - 1; }
int succ(int const i) { return i + 1; }
int apply(int f(int), int const x) {
// Oops, didn’t really mean to reassign ‘f’ here.
f = pred;
return f(x);
}
int main() {
printf("%i\n", apply(succ, 1));
return 0;
}
You can avoid this potential source of bugs by making the pointer const:
int apply(int (* const f)(int), int const x) {
// error: assignment of read-only parameter ‘f’
f = pred;
return f(x);
}
Given the abuse you can use with function pointers (&func, func, *func, **func, … all end up as the same value for a function func), there are few practical differences between the two. You can use fn * to indicate a pointer to function, which is not a trivial transform.
However, here's a mild adaptation of your code, using a non-parameter variable of type pfn and attempting (unsuccessfully) to use non-parameter variable of type fn. This does not compile, so there is a difference when used at file scope (global) or local scope and not in a parameter list.
pfn.c
typedef void (fn)(void);
typedef void (*pfn)(void);
static void callback(void)
{
printf("hello\n");
}
static void a(fn fn1)
{
fn fn2 = callback;
fn *fn3 = callback;
fn1();
fn2();
(*fn2)();
fn3();
(*fn3)();
}
static void b(pfn fn1)
{
pfn fn2 = callback;
fn1();
fn2();
}
int main(void)
{
a(callback);
b(callback);
return 0;
}
Compilation
$ gcc -g -O3 -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
> -Werror pfn.c -o pfn
pfn.c: In function ‘a’:
pfn.c:13:5: error: function ‘fn2’ is initialized like a variable
fn fn2 = callback;
^
pfn.c:13:8: error: nested function ‘fn2’ declared but never defined
fn fn2 = callback;
^
$
fn fn2 = callback;
is illegal in Standard C.
void a(fn fn1)
behaves exactly like void a(fn *fn1). It is a special syntax permitted only in function formal parameter lists, similar to how void b(int x[]) actually behaves exactly like void b(int *x). If you do sizeof fn1 you will get the size of a function pointer.
BTW you have redundant parentheses in your definition of fn, this is simpler:
typedef void fn(void);
The pointer version requires parentheses to associate the *.
have a look at the last segment Here
which helps you understand typedef of the fucntion's and function pointer better.
I have come across the line of code shown below.
I think it may be a cast to a function pointer that returns void and takes a void pointer. Is that correct?
(void (*)(void *))SGENT_1_calc
Yes, it is correct. I find that not very readable, so I suggest declaring the signature of the function to be pointed:
typedef void sigrout_t(void*);
I also have the coding convention that types ending with rout_t are such types for functions signatures. You might name it otherwise, since _t is a suffix reserved by POSIX.
Later on I am casting, perhaps to call it like
((sigrout_t*) SGENT_1_calc) (someptr);
Yes, it is. The function should be looking like this
void func(void*);
But the statement is missing a target, since a cast to nothing is useless. So it should be like
func = (void (*)(void *))SGENT_1_calc;
None of the existing answers show it in direct usage, that is, taking a function pointer and casting it in order to call the function. I was playing with this to show the content of my object as json, accessing both the function and the data through anonymous pointers:
#include <stdio.h>
#include <stdlib.h>
typedef struct box1_s{
int a;
char b[50];
}box1_t;
void box1_t_print(void* ptr){
box1_t* box = (box1_t*)ptr;
printf("{\"a\": %i, \"b\": \"%s\"}", box->a, box->b);
}
int main(){
void* print = (void*)box1_t_print;
box1_t mybox = {3, "Hi folks, it's me!"};
void* ptr = &mybox;
printf("mybox = ");
((void (*)(void*))print)(ptr);
return 0;
}
Output of the program:
mybox = {"a": 3, "b": "Hi folks, it's me!"}
Yes, this is a function pointer cast.
Function pointer casts
To help you with casting functions to pointers, you can define an alias for a function pointer type as follows:
typedef void void_to_void_fct(void*);
You can also define a type for a function that takes and returns values:
typedef int math_operator(int, int);
Later, you can store a function into a function pointer type like this:
void mystery(void* arg) {
// do something nasty with the given argument
};
int add(int a, int b) {
return a + b;
}
void_to_void *ptr1 = mystery;
math_operator *ptr2 = add;
Sometimes, you have a function like print_str :
void print_str(char* str) {
printf("%s", str);
}
and you want to store it in your function pointer that is agnostic to the argument type. You can then use a cast like this:
(void (*)(void *))print_str
or
(void_to_void_fct*)print_str
Why do we use function pointers?
Function pointers allow you to "store a function" inside a variable (indeed, you store the address of the function). This is very convenient when you want to allow some code to have diferent behavior depending on user input.
For exemple, suppose we have some data and some way to decode it. We could have the following structure to keep this information:
typedef char* decoder_type(char*);
struct encoded_data {
char* data;
decoder_type *decoder_fct;
};
char* decoding_function_1(char* data) {
//...
char* decoding_function_2(char* data) {
//...
This allows storing both the data and the function to later use them together to decode the data.