This question already has answers here:
Understanding typedefs for function pointers in C
(8 answers)
Typedef function pointer?
(6 answers)
Closed 9 years ago.
I am reading Linux kernel recently.
I find that in many cases they use the struct "typedef xxx f(xxx)", but I cannot understand how it works. (something like function pointer?)
Here is my test code.
#include<stdio.h>
typedef int Myfunc(int);
typedef int (*point_to_myfunc)(int);
static Myfunc example;
static int example(int a){
printf("example a=%d\n", a);
return 1;
}
static void example2(Myfunc* f){
printf("example2\n");
f(2);
}
static void example3(int (*)(int));
static void example3(int (*point_to_Myfunc)(int)){
printf("example3\n");
point_to_Myfunc(3);
}
int main(){
point_to_myfunc f=&example;
example2(f);
example3(f);
return 0;
}
Can anyone provide a brief explanation for me? Thx~
#include <stdio.h>
typedef int Myfunc(int);
Myfunc is the name of a type; it is a function taking an int argument and returning an int.
typedef int (*point_to_myfunc)(int);
point_to_myfunc is a pointer to a function taking an int argument and returning an int. You could also have: typedef Myfunc *ptr_to_myfunc; if you wished (another name for the same type).
static Myfunc example;
This says 'there exists a function called example of type Myfunc'.
static int example(int a)
{
printf("example a=%d\n", a);
return 1;
}
This is a possible implementation of example. You can't use a typedef name to like Myfunc in the definition of a function of that type.
static void example2(Myfunc *f)
{
printf("example2\n");
f(2);
}
This is a function that takes a pointer to a Myfunc. The line f(2); invokes the function pointed at with the argument 2 and ignores the returned value.
static void example3(int (*)(int));
This declares example3 as a function taking a pointer to a function that takes an int argument and returns an int result. It could have been written as static void example3(point_to_myfunc); or static void example3(ptr_to_myfunc); or static void example3(Myfunc *);.
static void example3(int (*point_to_Myfunc)(int))
{
printf("example3\n");
point_to_Myfunc(3);
}
This is an implementation of example3.
int main(void)
{
point_to_myfunc f = &example;
example2(f);
example3(f);
return 0;
}
This program has a variable f that's a pointer to a function. Interestingly, you could have:
point_to_myfunc f2 = example;
point_to_myfunc f3 = *example;
Etc. And they all mean the same thing.
You could also invoke them using:
(*f2)(101);
(**f3)(103);
The standard notation for the initialization would use neither the & nor the *. If you're an old school C programmer, you may well invoke the function pointer using the (*f2)(101) notation; before the C89 standard, that was the only way to invoke function pointers. Modern style tends to be f2(101); instead.
Vaughn Cato is correct,
In addition,
typedef int (*point_to_myfunc)(int);
defines a function pointer, it means point_to_myfunc is a type,we can use it like this:
point_to_myfunc f=&example;
now f is just like example(), we could f() to call method example
typedef int Myfunc(int);
This means that Myfunc is the type of a function which takes an int parameter and returns an int.
This line:
static Myfunc example;
is the same as saying
static int example(int);
which forward-declares the example function.
One use for this would be to make it clearer that a particular set of functions are used for a particular purpose.
typedef char CharacterConverter(char);
extern CharacterConverter make_upper_case;
extern CharacterConverter make_lower_case;
extern void process_string(char *s,CharacterConverter *f);
// easier to see that make_upper_case and make_lower_case are valid arguments.
typedef is useful when define a type.
For example:
char *a, b; defined a pointer "a", and a char b.
char *a, *b defined two char pointers.
If use typedef, it will be clear:
typedef char* PCHAR;
PCHAR a,b;
Now, both a and b is a char pointer.
typedef int Myfunc(int);
typedef int (*point_to_myfunc)(int);
the two lines defined a pair, a function format and a type of pointer which can point to the function, so it will be clear and more obvious when using them.
Related
I am having difficulty to figure out what is the use typedef here-
typedef char TYPE_SSOSettingError;
typedef void (*ans_executeDomainRegistration) (TYPE_SSOSettingError);
From the first line I understand that TYPE_SSOSettingError is defined as char.
From the next line I can figure out that ans_executeDomainRegistrationis a pointer to a function which is having return type of void and takes parameter of type char which in this situation is TYPE_SSOSettingError
Then what is the use of typedef in the last line?
The typedef is, as you noted, a pointer to a function. So it can be used to declare said pointer to said function and then bind it to an actual pointer to a function with said signature and then called as desired.
typedef char TYPE_SSOSettingError;
typedef void (*ans_executeDomainRegistration) (TYPE_SSOSettingError);
// ...
void somefunc(TYPE_SSOSettingError);
// ...
ans_executeDomainRegistration ptr = &somefunc;
The typical use case for this is with a callback function of some sort. It is used in the standard library for setting the terminate function etc. std::set_terminate, with the terminate handler typedef.
typedef void (*terminate_handler)();
std::terminate_handler set_terminate( std::terminate_handler f );
In more general terms, use of the typedef (and type aliases using) provides a technique to offer a better abstraction.
void (*ptr) (char) = &somefunc; // 1
ans_executeDomainRegistration ptr = &somefunc; // 2
Your case in point, it is unclear in line 1 what ptr will be used for, line 2 offers clearer intent, the ptr will be used as a function call for the execution of a domain registration and that function accepts an SSO settings error.
It is a technique to make the code easier to read, better, terse, or more succinct in order to express the concepts in the code (for some definition of easier, better etc.). Use them well; when not used well, they can also make the code more obscure, and harder to read and understand.
To make more clear declarations like this:
int register_callback(void (*execute) (TYPE_SSOSettingError));
vs
int register_callback(ans_executeDomainRegistration* execute));
Also, to make it clear what a function pointer should be.
You are right this is a typedef of a function pointer with return value void and parameter TYPE_SSOSettingError.
The typedef can be used to increase the readability of your code when
using a function pointer.
Function pointer declarations
For example declaring a function pointer fct_ptr1 and fct_ptr2 which are exactly the same:
// Type definition:
typedef void (*ans_executeDomainRegistration) (TYPE_SSOSettingError);
// Declarations:
ans_executeDomainRegistration fct_ptr1 = foo; // With typedef
void (*fct_ptr2) (TYPE_SSOSettingError) = foo; // Without typedef
Function declarations
Also if you have any function with a function pointer as parameter:
// Write:
void SomeFct(ans_executeDomainRegistration param) {...} // With typedef
// Instead of:
void SomeOtherFct(void (*param)(TYPE_SSOSettingError)) {...} // Without typedef
Conclusion
So as a result of using the typedef you see it is more familiar to
declare pointers or functions if you have declared a type for the function pointer.
typedef void (*ans_executeDomainRegistration) (TYPE_SSOSettingError);
typedefs a function pointer to a function of type void(char).
Example:
void foo(char) {
...
}
int main() {
ans_executeDomainRegistration f = &foo;
f('a');
}
The second typedef makes it so you have a defined type for later use.
Here an example to contrast a use with and without typedef.
#include <stdio.h>
typedef char TYPE_SSOSettingError;
typedef void(*ans_executeDomainRegistration) (TYPE_SSOSettingError);
void myprint(TYPE_SSOSettingError c)
{
printf("%c\n", c);
}
int main()
{
ans_executeDomainRegistration with_typedef = myprint;
void(*without_typedef) (TYPE_SSOSettingError) = myprint;
with_typedef('w');
without_typedef('o');
}
I suppose you've known about typedef, and you're asking about why to use defined typedef at 2nd typedef.
Then what is the use of typedef in the last line.
It's guaranteed that if TYPE_SSOSettingError gets changed, the parameter's type of ans_executeDomainRegistration will get changed too.
Think of a function which returns a function pointer of type ans_executeDomainRegistration.
Imagine something like:
ans_executeDomainRegistration getDomainRegistrationFunction(enum DomainType d)
{
return global_ans_executeDomainRegistration[getDomainindex(d)];
}
which is called like:
(*getDomain(MY_DOMAIN))(varSSOSettingError);
In C++ 11 you can use an alias declaration instead of the typedef that looks more clear.
For example
using ans_executeDomainRegistration = void ( * )( TYPE_SSOSettingError );
From this declaration it is seen that ans_executeDomainRegistration is a name for type void ( * )( TYPE_SSOSettingError ). That is this name denotes the type of pointer to function with one parameter and return type void.
So instead of writing in the program for example like
typedef char TYPE_SSOSettingError;
void myFunc( TYPE_SSOSettingError );
//...
void (*myFuncPtr1) (TYPE_SSOSettingError) = myFunc;
void (*myFuncPtr2) (TYPE_SSOSettingError) = myFunc;
you can write
ans_executeDomainRegistration myFuncPtr1 = myFunc;
ans_executeDomainRegistration myFuncPtr2 = myFunc;
This question already has answers here:
Function pointer to different functions with different arguments in C
(6 answers)
Closed 9 years ago.
is there any possibility for function pointer for addressing function with different no of arguments of same return type, if not any alternate would be helpful.. thanks in advance
example:
struct method
{
char *name;
void (*ptr)(?); //? : what to define as arguments for this
};
void fun1(char *name)
{
printf("name %s\n\r",name);
}
void fun2(char *name, int a)
{
printf("name %s %d\n\r",name,a);
}
//defined before main()
method def[]=
{
{"fun1",fun1},
{"fun2",fun2}
}
//some where in main()
//call for function pointer
def[1].ptr("try", 2);
typedef void (*myfunc)(char *,int);
struct method
{
char *name;
myfunc ptr;
};
method def[]=
{
//we store fun1 as myfun
//type void(char*,int) and use it this way
{"fun1",(myfunc)fun1},
{"fun2",fun2}
};
This is by theory undefined behavior, but in reality it should work on most platforms
* edit -> this works on all plaforms just like printf(const char*,...) does.
In C, you can make your function pointer declaration read
void (*ptr)();
Which means 'A pointer to a function returning void and expecting an unspecified number of argments.'
With that adjustement, your sample program works as expected to me. However, it may well be that you're venturing into undefined (or at least implementation defined) lands here - I don't know for sure and I'm not a language lawyer (however there are plenty of language lawyers frequenting SO, so I'm sure somebody can whip up the relevant section of the standard or prove that there is none). So maybe you should rather use
/* Here be dragons! */
void (*ptr)();
instead.
Solution #1:
void fun1(char *name, ...);
void fun2(char *name, ...);
Solution #2:
method def[]=
{
{"fun1",printf},
{"fun2",printf}
}
I would like to forward a callback to a function pointer. So I declare a static (int*) m_pointer1, as well as a method void RegisterCallback1( (int*)fct)
in class1.h:
public:
int RegisterCallback1( int (*fct) );
private:
static int (*m_Callback1);
in class1.cpp:
int class1::RegisterCallback1( int (*fct) )
{
m_Callback1= fct;
}
then, I want to forward the callback to the function pointer:
void class1::Callback1()
{
(*m_Callback1)();
}
But I get a compiler error "Expression must have (pointer-to)- function type
I have followed tutorial and read about function pointers and they seem to do it this way without any problems. Any ideas why?
EDIT:
So, I declare (int*)(void)m_Callback1 -Visual Studio requires a void there...-
Then how do I call the registerCallback function with the argument?
class1.RegisterCallBack1( ??? - class2::callback -??? );
static int (*m_Callback1) does not declate a function pointer, just a pointer to int: you forgot about the parameter list. You meant:
static int (*m_Callback1)();
and
int RegisterCallback1( int (*fct)() );
You haven't declared a function pointer, you've declared a normal data pointer. You are missing () at the end of the declaration.
You can try to limit the missing () errors pointed out by Oli and Dave by using a typedef for the callback function's signature: typedef int (*)() CallBack; This would at least have the merit of letting you think once about the precise number of brackets rather than at every point in your code where you use such a function.
This question is similar to what I'm trying to do Calling C++ member function pointer from a struct .
However my structure contains a member function pointer that is defined in a different class then the one the structure is defined and used in. Here is some example code of how my classes, structures and function pointers are laid out.
// Alpha.h:
class Alpha{
public:
void function1(char name[], int number);
void function2(char name[], int number);
void function3(char name[], int number);
typedef void (Alpha::*My_func_ptr)(char name[], int number);
static My_func_ptr functionTable[];
};
// Alpha.cpp:
#include "Alpha.h"
Alpha::My_func_ptr Alpha::functionTable[] = {
&Alpha::function1,
&Alpha::function2,
&Alpha::function3
};
void Alpha::function1(char name[], int number)
{
//some stuff
}
void Alpha::function2(char name[], int number)
{
//some stuff
}
void Alpha::function3(char name[], int number)
{
//some stuff
}
// Beta.h:
#include "Alpha.h"
typdef struct{
char bName[10];
Alpha::My_func_ptr fptr;
}ptr_structure;
class Beta{
public:
void betafunction();
Alpha alphaobject;
ptr_structure str_array[3];
};
// Beta.cpp:
#include "Beta.h"
void betafunction()
{
str_array[0].fptr = alphaobject.functionTable[0];
str_array[1].fptr = alphaobject.functionTable[1];
str_array[2].fptr = alphaobject.functionTable[2];
(str_array[0].fptr)("name", 1); //gives error expression must have
//(pointer-to-) function type
(this->*str_array[0].fptr)("name", 1);
//error pointer-to-member selection class types are incompatible "Beta" and "Alpha"
//sample function pointer call using function table from other class,
//this syntax compiles and runs without error.
(alphaobject.*Alpha::functionTable[0]("name", 1);
}
As you can see I can call the function pointer from an array, but can't seem to figure out how to call a function pointer from inside an array of structures.
When calling a through member function pointer, you need to have an instance of the object associated with that pointer:
(alphaobject.*(str_array[0].fptr))("name", 1)
^^^^^^^^^^^
I would think:
(object.*functionTable[0])(args, ...);
(objptr->*functionTable[0])(args, ....);
IIRC, the combination of object and the .* operator is like a big unary operator. So that has lower precedence to the [0] postfix. However, it also has lower prededence than the function call postfix operator (args, ...)
Analogy:
(*foo)(); /* classic C */
Of course the * operator is not required when calling a regular function. But if you do write it, you need the parens, because *foo() means something else.
You can go to one of two solutions, depending on how readable you want the code. The unreadable version (which might even be wrong, and I won't even try to compile):
void Beta::betafunction() {
Alpha a;
(a.*(strArray[0].fptr))("name",1);
}
But I would actually try to make things a bit simpler:
void Beta::betafunction() {
Alpha a;
Alpha::My_func_ptr mptr = strArray[0].fptr;
(a.*mptr)("name",1);
}
I believe the second to be much more readable, and the compiler can optimize away mptr pretty easily, so there is no point in trying to play guru with the syntax.
I need to pass something like a pointer that takes anything as a function parameter. You know, something without any predefined type or a type that can take anything like this:
void MyFunc( *pointer );
And then use it like:
char * x = "YAY!";
MyFunc(x);
int y = 10;
MyFunc(&y);
MyObj *b = new MyObj();
MyFunc(b);
And I don't want to use templates because I am mostly using C in my project.
Is there anything that can be used here except a function macro?
In C++, Boost.Any will let you do this in a type-safe way:
void func(boost::any const &x)
{
// any_cast a reference and it
// will throw if x is not an int.
int i = any_cast<int>(x);
// any_cast a pointer and it will
// return a null pointer if x is not an int.
int const *p = any_cast<int>(&x);
}
// pass in whatever you want.
func(123);
func("123");
In C, you would use a void pointer:
void func(void const *x)
{
// it's up to you to ensure x points to an int. if
// it's not, it might crash or it might silently appear
// to work. nothing is checked for you!
int i = *(int const*)x;
}
// pass in whatever you want.
int i = 123;
func(&i);
func("123");
You seem adverse to it but I'll recommend it anyway: if you're using C++, embrace it. Don't be afraid of templates. Things like Boost.Any and void pointers have a place in C++, but it is very small.
Update:
Well , I am making a small signals - slots - connections library to be
used with my gui toolkit. So that I can get rid of the Ugly WNDPROC. I
need these pointers for the connections.
If you need multi-target signals, Boost.Signals already provides a full and tested signals/slots implementation. You can use Boost.Bind (or std::bind, if you've got a C++0x compiler) to connect member functions:
struct button
{
boost::signal<void(button&)> on_click;
}
struct my_window
{
button b;
my_window()
{
b.on_click.connect(std::bind(&my_window::handle_click,
this, std::placeholders::_1));
}
void handle_click(button &b)
{
}
void simulate_click()
{
b.on_click(b);
}
};
If you only want a simple callback, Boost.Function (or std::function if you've got a C++0x compiler) will work well:
struct button
{
std::function<void(button&)> on_click;
}
struct my_window
{
button b;
my_window()
{
b.on_click = std::bind(&my_window::handle_click,
this, std::placeholders::_1);
}
void handle_click(button &b)
{
}
void simulate_click()
{
b.on_click(b);
}
};
You can use a function that takes a void*, but you must be aware of the pointer types that are not compatible with void*:
pointers to functions:
void MyFunc(void*);
MyFunc(&MyFunc); // WRONG
pointers to members:
void MyFunc(void*);
struct A { int x; };
MyFunc(&A::x); // WRONG
While these pointers are not compatible with void* (even with casting, on some compilers), they are themselves data. So you can pass a pointer to the pointer:
void MyFunc(void*);
void (*pfn)(void*) = &MyFunc;
MyFunc(&pfn); // ok
struct A { int x; };
int A::*px = &A::x;
MyFunc(&px); // ok
You can define the method as taking one void * argument. Of course, at that point, it's up to you to figure out what to do with the data (as far as accessing it or casting it.)
void MyFunc(void * ptr);
You could use:
void MyFunc( void* p){}
int g = 10;
MyFunc( (void*)&g );
void * is the way to do it. You can assign any pointer type to and from a void *. But to use the pointer in the called function, you'll have to know the type so you can create an appropriate local pointer or cast appropriately. You can encode a limited set of types as enum symbols, and perhaps use a switch to select type-specific behavior. But without a specific purpose or use-case, you might end up chasing your tail in a quest for generality for which C was never intended.
Another way would be to make a union to contain all the various types you know are needed.
typedef union {
int i;
char c;
float f;
} vartype;
Then if the value can carry around its own type-identifier, it becomes a tag-union or variant-record.
typedef struct {
enum type { INT, CHAR, FLOAT } type;
vartype var;
} varrec;