Question
I am learning how to dynamically load DLLs, but I do not understand this line of C code:
typedef void (*FunctionFunc)();
I have a few questions about it:
- Why is
typedefused here? - The syntax looks unusual. After
void, should there be a function name? It almost looks like an anonymous function. - Is this creating a function pointer that stores the memory address of a function?
I am confused about what this declaration means and how it works. Can someone clarify it?
Short Answer
By the end of this page, you will understand how function pointers work in C, why typedef is often used to simplify them, and how a declaration like typedef void (*FunctionFunc)(); creates a reusable type for pointing to functions. You will also see how this is useful when working with dynamically loaded DLL functions.
Concept
In C, a function pointer is a variable that can store the address of a function. This lets your program call a function indirectly.
That is especially useful when:
- passing functions to other functions
- selecting behavior at runtime
- working with callbacks
- loading functions from shared libraries or DLLs
The line:
typedef void (*FunctionFunc)();
means:
FunctionFuncis a type name- that type is a pointer to a function
- the function returns
void - the function takes an unspecified argument list in old-style C syntax
A clearer modern version is often:
typedef void (*FunctionFunc)(void);
This means: FunctionFunc is a type for "pointer to a function taking no arguments and returning nothing."
Why typedef is used
Without typedef, function pointer declarations are hard to read. gives that complicated type a simple name.
Mental Model
Think of a function pointer like a remote control with one programmed button.
- The actual function lives somewhere in memory.
- The function pointer does not contain the function itself.
- It contains the location of that function.
- When you use the pointer, you are saying: "go to that location and run that function."
Now think of typedef as a label maker.
Instead of repeatedly writing a complicated type like:
void (*)(void)
you give it a simple label:
FunctionFunc
So typedef does not create a function or a pointer variable by itself. It just creates a simpler name for a type.
Syntax and Examples
Basic syntax
A normal function declaration:
void greet(void);
A function pointer variable that can point to that kind of function:
void (*funcPtr)(void);
A typedef for that function pointer type:
typedef void (*FunctionFunc)(void);
A variable using that typedef:
FunctionFunc funcPtr;
Example 1: Assign and call a function pointer
#include <stdio.h>
void greet(void) {
printf("Hello from greet()\n");
}
int main(void) {
typedef void ;
FunctionFunc func = greet;
func();
;
}
Step by Step Execution
Consider this example:
#include <stdio.h>
typedef void (*FunctionFunc)(void);
void showMessage(void) {
printf("Message shown\n");
}
int main(void) {
FunctionFunc func = showMessage;
func();
return 0;
}
Step-by-step
1. Define a function pointer type
typedef void (*FunctionFunc)(void);
This creates a new type name, FunctionFunc.
That type means: pointer to a function that:
- takes no arguments
- returns
void
2. Define a real function
void {
();
}
Real World Use Cases
Function pointers are common in real C programs.
1. Dynamically loaded libraries and DLLs
When you load a DLL at runtime, you often get a raw function address from the system API. You cast or assign that address to a function pointer type and then call it.
Example use case:
- load a plugin
- find a function like
initialize - store it in a function pointer
- call it
2. Callbacks
Many C libraries ask you to provide a function they can call later.
Examples:
- sorting functions
- event handlers
- signal handlers
- GUI callbacks
3. Strategy selection
A program may choose one of several functions depending on configuration or user input.
For example:
- choose a compression algorithm
- choose a parser
- choose a logging function
4. Embedded systems
Function pointers are often used to connect hardware behavior to different handlers.
Examples:
- interrupt handlers
- device drivers
- command dispatch tables
5. State machines and command tables
Programs can store function pointers in arrays or structs to map commands to actions.
Example:
- command
startpoints tostartHandler
Real Codebase Usage
In real codebases, developers often use function pointer typedefs to make APIs easier to read and maintain.
Common patterns
1. Clear reusable type aliases
Instead of repeating complex declarations, teams define a named type once.
typedef void (*LogHandler)(const char *message);
This improves readability in structs and function parameters.
2. Validation after dynamic lookup
When loading a function from a DLL, developers usually check that the lookup succeeded before calling it.
if (func == NULL) {
return -1;
}
This is a guard clause that prevents crashes.
3. Storing callbacks in structs
typedef void (*OnEvent)(int code);
typedef struct {
OnEvent onStart;
OnEvent onStop;
} Handlers;
This keeps related behavior together.
4. Dispatch tables
Common Mistakes
1. Forgetting the parentheses around *name
Broken code:
void *func(void);
This is not a pointer to a function returning void. It is a function returning void *.
Correct code:
void (*func)(void);
2. Using () when you really mean no arguments
This declaration:
typedef void (*FunctionFunc)();
uses old-style syntax meaning the parameters are not specified.
For beginners, this is safer and clearer:
typedef void (*FunctionFunc)(void);
That explicitly means no arguments.
3. Assigning a function with the wrong signature
Comparisons
Function pointer declaration vs typedef alias
| Style | Example | Meaning | Readability |
|---|---|---|---|
| Direct declaration | void (*func)(void); | func is a pointer to a function | Harder to read |
| With typedef | typedef void (*FunctionFunc)(void); | FunctionFunc is a type alias | Easier to reuse |
() vs (void) in C
| Syntax | Meaning | Recommendation |
|---|---|---|
Cheat Sheet
Quick reference
Function pointer syntax
return_type (*pointer_name)(parameter_types);
Example:
int (*op)(int, int);
Typedef for function pointer
typedef return_type (*TypeName)(parameter_types);
Example:
typedef void (*FunctionFunc)(void);
Declare a variable using the typedef
FunctionFunc func;
Assign a function
func = showMessage;
or
func = &showMessage;
Call through the pointer
func();
FAQ
Why does C function pointer syntax look so strange?
C declarations are designed to resemble usage. Parentheses are needed to show that the name is a pointer to a function, not a function returning a pointer.
Does typedef void (*FunctionFunc)(); create a function?
No. It creates a type alias named FunctionFunc.
Is FunctionFunc a variable name?
No. After typedef, the name becomes a type name. You would create variables later using that type.
What is the difference between () and (void) in C?
() means the parameter list is not specified. (void) explicitly means no arguments. (void) is usually the better choice.
Can a function pointer hold any function?
No. It should only point to functions with a compatible signature.
Why are function pointers useful for DLLs?
When a DLL function is found at runtime, you receive its address. A function pointer lets you store that address and call the function.
Do I need to use &functionName when assigning a function pointer?
Usually no. In most cases, functionName works because the function name converts to a pointer automatically.
Mini Project
Description
Build a small C program that uses a function pointer typedef to choose and call different operations. This demonstrates the same core idea used when calling functions loaded from a DLL: you store a function address in a variable and call it through that variable.
Goal
Create a program that stores function addresses in function pointer variables and calls the selected function correctly.
Requirements
- Define a function pointer type with
typedef. - Create at least two functions with the same signature.
- Store one of those functions in a function pointer variable.
- Call the function through the pointer.
- Show that the pointer can be reassigned to a different function.
Keep learning
Related questions
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.
C Pointer to Array vs Array of Pointers: How to Read Complex Declarations
Learn the difference between pointer-to-array and array-of-pointers in C, plus a simple rule for reading complex declarations correctly.