I'm a little confused over how to declare a function pointer in a header file.
I want to use it in main and a file called menus.c and declare it in menus.h I assume.
We want to initialize to point to a certain function.
it looks like this:
void (*current_menu)(int);
What do we write in menus.c, menus.h and main?
A function pointer is still a pointer, meaning it's still a variable.
If you want a variable to be visible from several source files, the simplest solution is to declare it extern in a header, with the definition elsewhere.
In a header:
extern void (*current_menu)(int);
In one source file:
void (*current_menu)(int) = &the_func_i_want;
It's often helpful to use typedef with function pointers, so you can name the type to something descriptive:
typedef void (*MenuFunction)(int);
Then you would have a global variable of this type, probably in menus.c, and declared (with extern) in menus.h:
static void my_first_menu_function(int x)
{
printf("the menu function got %d\n", x);
}
MenuFunction current_menu = my_first_menu_function;
From main.c, you can then do:
#include "menu.h"
current_menu(4711);
to call whatever function is currently pointed at by current_menu.
A pointer function itself does not have a function definition. It's nothing more than a pointer to a type, the type being specified by the return type of the function and the parameter list. What you need to do is define a function with the same parameter list and return type, then use your pointer function to hold that function's address. You can then call the function through the pointer.
Related
First of all I am not a C expert but I thought I'd be able to break down C code. I am currently reading some open source repo and have no idea what the following statement within some struct in a header file means:
struct some_struct{
...
/* Callback when non-reply message comes in (inside db transaction) */
void (*billboardcb)(void *channel, bool perm, const char *happenings);
...
}
I thought functions cannot be declared like methods within structs. But if this is a variable (called billboardcb) why are there all these paremeters? I did not find a macro called billboardcb in this code base.
A function pointer is a pointer that stores an address to a function. Function pointers can live inside structs just like any other pointer. The (void *channel, bool perm, const char *happenings) parameters listed after void (*billboardcb) are the function's parameters. The void preceding the (*billboardcb) pointer indicates that the function returns nothing.
If you search for where the some_struct struct is instantiated, you'll likely find the actual function assigned to this pointer. The function assigned to the pointer will be declared like any other function, with its address then stored in the struct by assigning the function's memory address to the struct's pointer.
It's a pointer to function, the function pointer is called billboardcb. The pointer can only point to a function with the 3 parameters that are:
1) void*
2) bool
3) const char *
The pointer can be assigned by just giving it an address of another function with compatible format.
I am trying to understand what this means, the code I am looking at has
in .h
typedef void (*MCB)();
static MCB m_process;
in .C
MCB Modes::m_process = NULL;
And sometimes when I do
m_process();
I get segmentations fault, it's probably because the memory was freed, how can I debug when it gets freed?
It defines a pointer-to-function type. The functions return void, and the argument list is unspecified because the question is (currently, but possibly erroneously) tagged C; if it were tagged C++, then the function would take no arguments at all. To make it a function that takes no arguments (in C), you'd use:
typedef void (*MCB)(void);
This is one of the areas where there is a significant difference between C, which does not - yet - require all functions to be prototyped before being defined or used, and C++, which does.
It introduces a function pointer type, pointing to a function returning nothing (void), not taking any parameters and naming the new type MCB.
The typedef defines MCB as the type of a pointer to a function that takes no arguments, and returns void.
Note that MCB Modes::m_process = NULL; is C++, not C. Also, in C, the typedef should really be typedef void (*MCB)(void);.
I'm not sure what you mean by "the memory was freed". You have a static pointer to a function; a function cannot be freed. At most, your pointer has been reset somewhere. Just debug with a memory watch on m_process.
Let's take an example
typedef void (*pt2fn)(int);
Here, we are defining a type pt2fn. Variables of this type point to functions, that take an integer as argument and does not return any value.
pt2fn kk;
Here, kk is a variable of type pt2fn, which can point to any function that takes in an integer as input and does not return any value.
Reference:https://cs.nyu.edu/courses/spring12/CSCI-GA.3033-014/Assignment1/function_pointers.html
It's a function pointer. You get a SEGMENTATION FAULT because you are trying to make a call to a function which address is invalid (NULL).
According to your specific sample, the function should return no value (void) and should receive no parameters ().
This should work:
void a()
{
printf("Hello!");
}
int main(int arcg, char** argv)
{
m_process = a;
m_process(); /* indirect call to "a" function, */
// Hello!
}
Function pointers are commonly used for some form of event handling in C. It's not its only use though...
I'm trying to learn c, so I tried reading some source code.
But I have no idea what this might mean:
static const char*(*const functab[])(void)={
ram,date
};
The first part, static const char* is fine, as it seems to be a function (has an argument of type void), static should mean that it is only visible in this file and const char* should mean that the value cannot be changed but the address can be changed.
But in that case, it doesn't make sense after the last part following the function name, as it was the case with
static const char * date(void);
static const char * ram(void);
Instead of the function name there is (*const functab[]), a const array called functab containing addresses?
Is this some kind of wrapping function containing the functions ram and date? Some alternative way of declaring arrays?
functab is an array of function pointers (array of const function pointers, to be exact), which returns const char* and accepts no arguments.
Later,
... = { ram, date };
is a brace-enclosed initializer list which serves as the initializer for the array.
This is the way to define array of function pointers in C. So instead of calling function as ram(), using this array you can call it by (* functab[1]).
Below discussion has good examples of array of function pointer:
How can I use an array of function pointers?
Short answer: Here functab is an array of function pointers, and the array is initialized with pointers to functions ram and date. This also explains the name functab which is likely from "FUNCtion TABle".
Long answer: In C you can get a pointer to a function and save it to a variable. A variable used in this fashion is known as a function pointer.
For example, funcptr variable below will contain the address of do_stuff's entry point:
int do_stuff(const char* x) { ...do stuff.. }
...
ftype_t funcptr = &do_stuff;
...
(*funcptr)("now"); // calls do_stuff()
This will only work if you have already defined the type of funcptr, which is ftype_t here. The type definition should take this form:
typedef int (*ftype_t)(const char*);
In English, this means ftype_t is being defined as a type of function that takes const char* as its only argument and returns int.
If you didn't want to typedef only for this, you could have achieved the same thing by doing below:
int (*funcptr)(const char*) = &do_stuff;
This works, but its syntax is confusing. Also it gets quite ugly if you attempt to do something like building an array of function pointers, which is exactly what your code does.
Shown below is equivalent code, which is much easier to understand:
typedef static const char*(*myfn_t)(void);
const myfn_t functab[] = { &ram, &date };
(The & (address of) is usually optional, but recommended. )
Complex variable declarations need to be read inside out in C:
functab is the identifier of the variable, so we start reading here...
functab[] it is an array...
*const functab[] of constant pointers...
(*const functab[])(...) to functions...
(*const functab[])(void) that take no arguments...
const char*(*const functab[])(void) but return a const char*.
The meaning of static depends on whether it's outside or inside of a function. If it's outside, the static means that functab is declared with file scope (i.e. a global variable that's only visible inside a single .c file). If it's inside a function, it means that functab is a global variable that's only visible inside that function.
The = { ram, date } initialize the array with two members. Both ram and date should be functions that are declared as const char* ram(void).
The effect of this declaration is, that the following function calls are equivalent:
const char* result = ram();
const char* result = functab[0]();
The code I am using has this statement:
typedef void ( udp_data_notify )(OS_FIFO * pfifo, WORD port);
This looks like a declaration of a function pointer for udp_data_notify, however there is no *. Can it still be a function pointer without an asterisk?
Here is a statement that uses udp_data_notify:
void RegisterUDPFifoWithNotify( WORD dp, OS_FIFO *pnewfifo , udp_data_notify * nudp)
Any help as to what is happening would be appreciated!
A typedef such as:
typedef void name(int);
(the parenthesis around name are redundant) will define name as the type of a function, not a function pointer. That would be:
typedef void (*pname)(int);
You are probably wondering what they are good for. Well, function types are not very useful, other than for declaring pointers:
name *pointer_to_function;
And that can be made arguably more readable with the other typedef:
pname pointer_to_function;
That's because you cannot define a variable of type function. If you try, you will simply write the prototype of a function, but in a quite obfuscated syntax:
name foo; //declaration (prototype), not variable
void foo(int x) //definition
{
}
But note that you cannot use the typedef to define the function:
name foo {} //syntax error!
As already said, the typedef declares an alias for function type. When you want to use it to declare a function pointer, an asterisk is required (udp_data_notify* x). A declaration without the asterisk (udp_data_notify x) would be a function declaration, except in one special case. When used in a parameter a function type is automatically turned into the corresponding function pointer type:
typedef void F(void);
void foo(F a, F* b) // special case; a and b are both function pointers
{
F c; // function declaration
F* d; // function pointer
}
The typedef you show declares udp_data_notify to be an alias for a function type. Then the parameter declaration udp_data_notify *nudp declares nudp to be a pointer to a function of that type. There is no function call here.
Regarding the function-call operator (postfix ()), the expression that designates the called function must be a pointer to a function. When you call a function normally, without a pointer, such as sqrt(2), the function is automatically converted to a pointer for you. So sqrt(2) is actually (&sqrt)(2). When you call a function with a pointer, the call is in the right form already.
I'm pretty new to C, and I'm having a really hard time reading this line of code and understanding it:
typedef void (*getnxtbyte_t)(void *stream);
From looking around, I now know that it is for a pointer pointing to a function. But could anyone help me clarify this even further? What is the name of this new type? What function is it pointing to? Is the parameter of the function (void* stream)?
Thanks in advance!
It is a tricky syntax to get used to.
What is the name of this new type?
The type is getnxtbyte_t. (You can read that trailing _t as "type". It's a popular convention.)
A variable of type getnxtbyte_t can hold the address of a function that takes one void * parameter and has return type void.
What function is it pointing to?
Wrong question.
That code merely defines the type. No variables are created so there's no "it" to point to anything.
If you know of a function with the correct signature, such as:
void some_func(void*) {}
You may now create a pointer to it using that typedef:
getnxtbyte_t my_function_pointer = some_func;
This typedef creates a type called getnxtbyte_t. That type is for a pointer to a function that returns void (i.e. nothing), as shown in the second word. That function takes a single parameter, which is a void *, shown by stream.
So if you had a function with a declaration like this:
void some_function(void *any_name);
Then you could use a typedef like the one in your post:
void *some_param = NULL;
typedef void (*getnxtbyte_t)(void *stream); // declare typedef
getnxtbyte_t func = some_function; // assign
func(some_param); // call
The function pointer type name is getnxtbyte_t. It's not pointing to anything now -- this is a type of pointer, not an actual pointer. It's just like saying
typedef struct foo {int x;} Foo;
you define a type Foo, but no actual instance of that type. And finally, yes, the function takes a single void* argument, and returns void.
I am also new to C, so if there are any errors please correct me.
A pointer that points to a function is formatted like so:
datatype (*POINTER_NAME)(PARAMETERS);
So that's the data type the pointed function returns, the name of the pointer and the parameters the pointed function takes.
Here's how a function pointer looks compared to a normal function declaration:
// normal function declaration
void getnxtbyte_t(void *stream);
// function pointer
void (*getnxtbyte_t)(void *stream);
typedef allows us to create our own type.
// will create a type called getnxtbyte_t
typedef void (*getnxtbyte_t)(void *stream);
At this point we have only declared a type; we are not pointing to anything. So let's create a pointer named func_ptr and point it to a function.
// func_ptr is a pointer of type getnxtbyte_t
getnxtbyte_t func_ptr = another_function;
// calling func_ptr is now the same as calling another_function
func_ptr(an_argument);
// had we not used typedef, we would type:
void (*getnxtbyte_t)(void *stream) = another_func;
getnxtbyte_t(an_argument);