views:

437

answers:

5

Instead of declaring a function pointer typedef for a function, is it possible to get it from the function declaration?

Typically,

int foo(int x);
typedef int (*fooFunc)(int);
fooFunc aFunc;

What I want:

int foo(int x);
foo* aFunc;

I want to use it for dlsym:

foo* aFunc;
aFunc = dlsym(lib, "foo");
aFunc(x);

If I update foo and forgot to update fooFunc, or vice versa, that would be bad. Also, I may have many functions and it would be more work to maintain both the function declarations and the function pointer typedefs that are associated with those functions.

Conclusion: AndreyT's answer is the most portable but if you code for gcc then typeof is a great solution.

+2  A: 

Simple answer: no, that doesn’t work. foo is a specific function which has a prototype (int (int)). Using foo in the way you did would be a bit like using an int to declare another int:

4 x; // expect this to be the same as int x

That said, there might be compiler extensions which make that work. I know that the upcoming C++ standard will have the decltype keyword to allow that. Using that, the following might work (untested, since I don’t have a supporting compiler handy):

int foo(int x);

decltype(&foo) aFunc = dlsym(lib, "foo");
Konrad Rudolph
+5  A: 

If you have gcc, typeof works.

Update

$ cat fxf.c
#include <stdio.h>

int main(int argc, char **argv) {
  typedef __typeof__ (main) function_of_same_type_as_main_t;
  function_of_same_type_as_main_t *f;

  printf("main() called.\n");
  f = main;
  if (argc) f(0, NULL);
  return 0;
}
$ /usr/bin/gcc -std=c89 -pedantic -Wall -Wextra -o fxf fxf.c
fxf.c:3: warning: unused parameter ‘argv’
$ ./fxf
main() called.
main() called.
pmg
You are correct. typeof does work in gcc. See example:#include <stdio.h>int foo(int x);int main(void){ int y; __typeof__(foo) *aFunc = NULL; aFunc = foo; y = aFunc(10); return 0;}int foo(int x){ return x * 2;}
KlaxSmashing
This is not "C syntax" though, which you appeared to be talking about in your question.
AndreyT
@KlaxSmashing: Your example causes undefined behaviour because of the cast from `void*` (`NULL`) to function pointer (`typeof (foo)`).
Joe D
+6  A: 

If you are talking about a declaration specifically, i.e. a non-defining declaration of a function, you can remove the redundancy by defining a typedef-name for function type and using it in both cases - to declare the function itself and to declare a pointer to it, like this

typedef int FuncType(int); /* <- function type */
FuncType foo; /* <- declaration of `int foo(int)` */
FuncType *aFunc; /* <- definition of `int (*aFunc)(int)` */

I.e. typedef-names can be used in non-defining function declarations. However, you can't use a typedef name in function definition, meaning that later you'll still have to do

int foo(int x) /* <- no way to use the above `FuncType` here */
{
  /* whatever */
}

which basically renders the above trick virtually useless.

Of course, this doesn't help you to generate a pointer from an existing non-modifiable function declaration, if that's your situation.

AndreyT
I saw this here on StackOverflow, this is very clever and oh so close. But I want the function to have the actual name "foo" as well because I look up the function name. Suppose you are creating an API where a number of other developers will write shared library plugins implementing your API functions: foo, bar. You will use "foo" and "bar" to look up those functions, and you will use the correct function type to execute them.I could write up the API header as: "Create a function called foo with the function type fooType ..." but I'd rather have it compiler enforced.
KlaxSmashing
I'm not sure I understand that comment. When you declare `FooType foo` above, you *are* declaring a function that has actual name `foo`.
AndreyT
Just so it's clear: If you put the typedef and the FuncType foo; declaration in a header, and the actual function foo in a file that includes that header, then the compiler will throw an error if you mis-match the types. The FuncType foo; declaration is just like you'd said 'int foo(int x);' in a header.
Michael Kohne
A: 

It is not possible. However, you can write some code that would generate a warning, so that you would catch type mismatch. The following code generates an assignment from incompatible pointer type warning.

#include <stdio.h>

int foo(int, int);
typedef  int(*fooFunc)(int);

fooFunc myfunc;

int foo(int x, int y)
{
    return 2*x + y;
}

int main(int argc, char **argv)
{
    myfunc = foo;
    printf("myfunc : 0x%x\n", (unsigned int)myfunc);
    return 0;
}

Of course, this means you would have to write this test code where the foo function is visible, so this is still more code to add for each function type. The solution here is probably a code generator, that would generate a proper header file containing both functions and their associated typedefs

shodanex
A: 

Not quite the same, but you can typedef the function and use it for both the prototype and the pointer.

typedef int fooFunc(int);
fooFunc foo;
fooFunc *aFunc;
Randy Proctor
Nevermind, beaten.
Randy Proctor
Interesting: I was expecting to get compilation errors, but neither 'gcc -std=c99 -pedantic' nor Solaris C (v12) with 'cc -v' complains. What you can't do, though, is define foo using the typedef name: `fooFunc foo { ... }` does not work, and neither does: `fooFunc foo(int n) { ... }`.
Jonathan Leffler