I have a struct that contains a declaration like this one:
void (*functions[256])(void) //Array of 256 functions without arguments and return value
And in another function I want to define it, but there are 256 functions!
I could do something like this:
struct.functions[0] = function0;
struct.functions[1] = function1;
struct.functions[2] = function2;
And so on, but this is too tiring, my question is there some way to do something like this?
struct.functions = { function0, function1, function2, function3, ..., };
EDIT: Syntax error corrected as said by Chris Lutz.
I have a struct that contains a declaration like this one:
No you don't. That's a syntax error. You're looking for:
void (*functions[256])();
Which is an array of function pointers. Note, however, that void func() isn't a "function that takes no arguments and returns nothing." It is a function that takes unspecified numbers or types of arguments and returns nothing. If you want "no arguments" you need this:
void (*functions[256])(void);
In C++, void func() does mean "takes no arguments," which causes some confusion (especially since the functionality C specifies for void func() is of dubious value.)
Either way, you should typedef your function pointer. It'll make the code infinitely easier to understand, and you'll only have one chance (at the typedef) to get the syntax wrong:
typedef void (*func_type)(void);
// ...
func_type functions[256];
Anyway, you can't assign to an array, but you can initialize an array and copy the data:
static func_type functions[256] = { /* initializer */ };
memcpy(mystruct.functions, functions, sizeof(functions));
I had the same problem, this is my small program to test the solution. It looks pretty straightforward so I thought I'd share it for future visitors.
#include <stdio.h>
int add(int a, int b) {
return a+b;
}
int minus(int a, int b) {
return a-b;
}
int multiply(int a, int b) {
return a*b;
}
typedef int (*f)(int, int); //declare typdef
f func[3] = {&add, &minus, &multiply}; //make array func of type f,
//the pointer to a function
int main() {
int i;
for (i = 0; i < 3; ++i) printf("%d\n", func[i](5, 4));
return 0;
}
You can do it dynamically... Here is a small example of a dynamic function array allocated with malloc...
#include <stdio.h>
#include <stdlib.h>
typedef void (*FOO_FUNC)(int x);
void a(int x)
{
printf("Function a: %d\n", x);
}
void b(int x)
{
printf("Function b: %d\n", x);
}
int main(int argc, char **argv)
{
FOO_FUNC *pFoo = (FOO_FUNC *)malloc(sizeof(FOO_FUNC) * 2);
pFoo[0] = &a;
pFoo[1] = &b;
pFoo[0](10);
pFoo[1](20);
return 0;
}
From the top of my head and untested.
// create array of pointers to functions
void (*functions[256])(void) = {&function0, &function1, &function2, ..., };
// copy pointers to struct
int i;
for (i = 0; i < 256; i++) struct.functions[i] = functions[i];
EDIT: Corrected syntax error as said by Chris Lutz.
You could do that while declaring your struct instance:
function_structur fs = { struct_field1,
struct_field2,
{function0, function1, ..., function255},
struct_field3,
... };
You cannot use this shortcut for initialize arrays after the array has been declared: if you need to do that, you'll have to do it dynamically (using a loop, a memcpy or something else).
If you want to post-initialize an array using form like {func1, func2, ...}, this can be accomplished in the following way (using GCC):
UPD (thanks to Chris Lutz for remarks)
Define a macro like this:
#define FUNCTION_VECTOR_COPY(destVec, sourceVec) memcpy(destVec, sourceVec, sizeof(sourceVec))
And pass source vector using Compound Literals, as follow:
#include <string.h>
...
void (*functions[256])();
...
FUNCTION_VECTOR_COPY (functions, ((void(*[])()) {func1, func2, func3}));
Related
I have a program, what it does isn't too important, I am mostly curious of the following:
If I have a struct that has pointers to a function, can I pass parameters into the function using that pointer? Here is part of my code
edit: I realized I was a little vague:
So is there anyway to use the variable 'x' of type funcs, to pass parameters into the my_closeit and my_openit using the pointer's initialized by x = {&openit, &closeit}; in the main function? By doing x -> or x. ?
Another Edit:
Would it be x.openit(some pointer, some int); ?
#include<stdio.h>
int my_openit(char* name, int prot);
void my_closeit(void);
typedef struct funcs
{
int (*openit)(char *name, int prot);
void (*closeit)(void);
}funcs;
//I know the first 'funcs' is unnecessary
int main()
{
funcs x = {&my_openit, &my_closeit};
return 0;
}
int my_openit(char* name, int prot)
{
return 0;
}
void my_closeit(void)
{
}
can I pass parameters into the function using that pointer?
Yes, obviously, or it wouldn't be of any use. In your case:
int result = x.openit("something", 123);
Yes, just use function call expression through the pointers:
int r = x.openit("myfile",0);
x.closeit();
I accidentally forgot to add (int) when defining a function pointer, and my program still worked.
I wold like to know if there is any case where it would not work.
my code:
#include <stdio.h>
void f1(int var)
{
printf("this is f1 and var is: %d\n", var);
}
void f2(int var)
{
printf("this is f2 and var is: %d\n", var);
}
void f3(int var)
{
printf("this is f3 and var is: %d\n", var);
}
typedef void (*f_ptr)(int);
// pq eu poderia escrever: typedef void (*f_ptr)(); e o programa funcionaria normalmente?
typedef int n_casa;
int main()
{
f_ptr ptr[] = {f1, f2, f3};
int c = 0;
while (c < 3)
{
ptr[c](c);
++c;
}
return 0;
}
both typedef void (*f_ptr)(int); and typedef void (*f_ptr)(); worked in my program.
They are different.
typedef void (*f_ptr)(int) declares a funciton pointer that takes only one int argument, and returns nothing.
While for typedef void (*f_ptr)(), the function pointer takes an UNSPECIFIED number of arguments, and returns nothing.
According to the SEI CERT C Coding Standard, it is recommended to explicitly specify void when a function accepts no arguments.
From my little assembly experience: When you call a function with an argument, it pushes the argument onto the stack and then executes the function. Then the function reads the arguments from the top of the stack.
If you call f_ptr with no arguments, you won't get an error, you'll just get a garbage value in var. If you call it with 100 arguments, you'll just get the first one.
I think the only reason the compiler doesn't stop you is that it isn't smart enough to.
When I try to compile the following line
int* x[](), (*y)();
I get the error "x declared as an array of functions of type int()"
You cannot really declare an array of functions, but you can have an array of function pointers, which will probably give you the same effect, because you can invoke them without explicit dereferencing.
The following will declare an array of 5 function pointers which return int*.
int* (*x[5])();
The website cdecl will let you play with various pointer declarations to see what they mean in English.
Here is the golden rule for reading C declarations, stolen from this old article.
Start at the variable name (or innermost construct if no identifier is
present. Look right without jumping over a right parenthesis; say what
you see. Look left again without jumping over a parenthesis; say what
you see. Jump out a level of parentheses if any. Look right; say what
you see. Look left; say what you see. Continue in this manner until
you say the variable type or return type.
When applied to the declaration above, we say:
x is an array of 5 pointers to functions returning pointer to int.
As SteveCox correctly commented below, we note that if we run into a type qualifier on the left hand side when following the above rule, it will describe the type to its left rather than its right. For example, the following declaration declares an array of 5 pointers to functions returning const pointer to int, not pointer to const int.
int* const (*x[5])();
Try this for an array of 2 function pointers.
#include <stdio.h>
int *first(void) { return NULL; }
int *second(void) { return NULL; }
int main(void) {
int *(*fx[2])(void);
fx[0] = first;
fx[1] = second;
/* ... */
if (fx[0]() == fx[1]()) {
printf("Calling both functions returns the same value.\n");
}
return 0;
}
A practical application might look like:
#include <ansi_c.h>
int add_(int, int);
int sub_(int, int);
int mul_(int, int);
int div_(int, int);
enum {
ADD,
SUB,
MUL,
DIV
};
int (*mathOps[4])(int, int);
int main(void)
{
int i;
mathOps[ADD]=add_;
mathOps[SUB]=sub_;
mathOps[MUL]=mul_;
mathOps[DIV]=div_;
for(i=ADD;i<=DIV;i++)
{
printf("results are: %d\n", mathOps[i](3, 3));
}
getchar();
return 0;
}
int add_(int a, int b)
{
return a + b;
}
int sub_(int a, int b)
{
return a - b;
}
int mul_(int a, int b)
{
return a * b;
}
int div_(int a, int b)
{
return a / b;
}
I have done some research about how to use function pointers in C and I was trying to do some model of an object-oriented kind of thing. So to model such a thing I have been told I would have to add function pointers to the structs, so that they would be kind of 'an object'.
As I am pretty new on programming in C, this question may seem a little stupid (or very easy to answer), but on the Internet, I just found examples concerning C++ and that's not what I am searching.
Here is an example I would like to show, so that you can easily understand what my question is about:
try.h-file:
struct thing {
void (*a)(int, int);
};
void add(int x, int y);
try.c-file:
#include <stdio.h>
#include <stdlib.h>
#include "try.h"
void add(int x, int y) {
printf("x + y = %d\n", x+y);
}
int main(int argc, char* argv[]) {
struct thing *p = (struct thing*) malloc(sizeof(struct thing));
p->a = &add;
(*p->a)(2, 3);
free(p);
p = NULL;
return 0;
}
As an example I would want to have always x = 2, so the function pointer in struct thing would be this kind of pointer: void (*a)(int) and not void (*a)(int, int) anymore.
How can I bind the argument x = 2 when passing the function pointer to the struct (line p->a = &add;)? Is this even possible in C? In C++ I have seen something like std::bind, but I wasn't able to do this in C.
The function pointer has to have the same signature (type and arguments) as the function it points to, so you can't really do it like that.
You could wrap the bind and the call in another couple of functions:
struct thing {
void (*a)(int, int);
int x;
};
...
void bind1st( struct thing *p, int arg )
{
p->x = arg;
}
void call( struct thing *p, int arg )
{
p->a( p->x, arg );
}
You'll want to experiment with this a bit, but that should get you started.
I've had similar problems,and I used the following method to resolve, use gcc to compile it work, use clang to compile it do not work.
#include <stdio.h>
typedef int (*add_t) (int);
add_t add2(int x) {
int add1(int y) {
return x + y;
}
return add1;
}
int main() {
//add2(2);
printf("%d\n", add2(2)(3));
}
A way that no one have talked about yet is to use some JIT logic (I won't provide a working example right now, because I've not yet tried it, but I will use it at some time for a RPC library). This is not strictly speaking a C language feature, and it's feasible only on CPU/MCU architecture where you can write to an executable memory segment (it's possible on x86_64, x86, some ARMs etc.).
The principle is really just to construct a function dynamically that will call the wrapped function in a similar way python defines dynamically nested functions.
Some library you can use for it : libgccjit, libjit, gnu-ligthning, llvm etc.
I think this is the best solution .
typedef void(*call_type)();
call_type bind(void (*f)(int,int), int a, int b) {
void call() {
f(a,b);
}
return &call;
}
void f(int a, int b){
printf("%d, %d", a, b);
}
int main(){
call_type c = bind(f, 5, 4);
c();
}
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().