Question

Typedef Function Pointers in C and C++

cppcpointerstypedef

Question

While learning to dynamically load DLLs, I encountered this declaration:

typedef void (*FunctionFunc)();

What does this declaration mean?

  • Why is typedef used here?
  • Why is there no function name immediately after void?
  • Does this create a function pointer that can store the memory address of a function?

Please clarify the syntax and how it is used when loading functions from a DLL.

Short Answer

By the end of this page, you will understand how to read a function-pointer declaration, why typedef gives it a reusable name, and how such pointers are used to call functions loaded from a DLL at runtime.

Concept

typedef void (*FunctionFunc)(); creates a type alias named FunctionFunc.

That alias means:

“A pointer to a function that takes no arguments and returns void.”

It does not create a function and it does not create a function-pointer variable by itself. It only defines a convenient name for that type.

typedef void (*FunctionFunc)();

Read it from the identifier outward:

  • FunctionFunc is inside (* ... ), so it is a pointer.
  • () means that pointer points to a function with no parameters.
  • void at the beginning means that function returns no value.
  • typedef says that this whole declaration defines a type name rather than a variable.

After the alias exists, you can declare an actual variable:

FunctionFunc functionPointer = nullptr;

That variable can later hold the address of a compatible function.

Function pointers matter when behavior is selected at runtime. Dynamic DLL loading is one example: a program can load a library, look up an exported function by name, store its address in a function pointer, and call it without linking to that library at build time.

Mental Model

Think of a function as a machine in a workshop. Its address tells you where that machine is located.

A function pointer is a labelled note that can hold the location of a compatible machine. Before using the note, you must know what kind of machine it refers to:

  • What inputs does it accept?
  • What output does it produce?

FunctionFunc is the label for one kind of note:

“This note points to a machine that accepts no input and produces no returned value.”

typedef is like creating that short label so you do not need to write the full, complicated description every time.

Take Quiz

Syntax and Examples

The direct syntax for declaring a pointer to a function is:

return_type (*pointer_name)(parameter_types);

For a function that takes no parameters and returns void:

void (*functionPointer)();

The parentheses around *functionPointer are essential. They say that functionPointer is a pointer to a function.

Naming the type with typedef

typedef void (*FunctionFunc)();

Now FunctionFunc can be used like a normal type name:

FunctionFunc functionPointer = nullptr;

Assigning and calling a function

#include <iostream>

void sayHello()
{
    std::cout << "Hello\n";
}

typedef void (*FunctionFunc)();

int main()
{
    FunctionFunc functionPointer = &sayHello;

    functionPointer();     // Calls sayHello
    (*functionPointer)();  // Also calls sayHello
}

Both call forms are valid. In C and C++, calling through functionPointer() is usually clearer.

The declaration is not an anonymous function. void is the function's return type. The function pointer's name is FunctionFunc in the typedef declaration, and functionPointer in the variable declaration.

Step by Step Execution

Consider this program:

#include <iostream>

void start()
{
    std::cout << "Starting...\n";
}

typedef void (*FunctionFunc)();

int main()
{
    FunctionFunc action = &start;
    action();
}

Execution proceeds as follows:

  1. start is defined. It is a function with this signature:

    void start();
    
  2. typedef void (*FunctionFunc)(); defines FunctionFunc as a type meaning “pointer to a void() function.” No memory is allocated for a pointer at this point.

  3. FunctionFunc action = &start; creates the variable action.

  4. &start is the address of the start function. Because start has the compatible signature void(), its address can be stored in action.

  5. action(); follows the stored address and executes start.

  6. start writes Starting... and returns no value because its return type is void.

Real World Use Cases

Function pointers are useful whenever code needs to choose or receive behavior dynamically.

  • Dynamically loaded DLLs: Load a DLL at runtime and retrieve exported function addresses with GetProcAddress on Windows.
  • Callbacks: Give a library a function to call later, such as an event handler or comparison function.
  • C APIs: Many C libraries accept function pointers for logging, memory allocation, parsing, and error handling.
  • Plugin systems: A host program can load optional modules and call known exported entry points.
  • Table-driven behavior: A command number or state can select one of several functions from an array of function pointers.

For example, the C standard library sorting function qsort receives a comparison function pointer so it can sort many kinds of data.

Take Quiz

Real Codebase Usage

In real code, developers typically give function-pointer types meaningful names and validate them before calling them.

Dynamic DLL loading on Windows

#include <windows.h>
#include <iostream>

using FunctionFunc = void (*)();

int main()
{
    HMODULE library = LoadLibraryA("plugin.dll");
    if (library == nullptr)
    {
        std::cerr << "Could not load plugin.dll\n";
        return 1;
    }

    auto rawAddress = GetProcAddress(library, "RunPlugin");
    if (rawAddress == nullptr)
    {
        std::cerr << "RunPlugin was not found\n";
        FreeLibrary(library);
        return 1;
    }

    auto runPlugin = reinterpret_cast<FunctionFunc>(rawAddress);
    runPlugin();

    FreeLibrary(library);
}

Important real-project practices:

  • Use a clear alias such as RunPluginFn or FunctionFunc.
  • Check that the library loaded successfully.
  • Check that the symbol lookup succeeded before calling it.
  • Keep the DLL loaded for as long as any pointer into it may be called.
  • Ensure the return type, parameters, and calling convention exactly match the exported function.

Modern C++ often uses using instead of typedef because it is easier to read:

using FunctionFunc = void (*)();

It defines the same type as the original typedef form.

Common Mistakes

Forgetting parentheses

This does not declare a function pointer:

void *functionPointer();

It declares a function named functionPointer that takes no arguments and returns void*.

Use parentheses around the *:

void (*functionPointer)();

Treating typedef as a variable declaration

typedef void (*FunctionFunc)();

This does not allocate storage for a pointer. Declare a variable separately:

FunctionFunc callback = nullptr;

Using an incompatible function signature

int returnsNumber()
{
    return 42;
}

using FunctionFunc = void (*)();
FunctionFunc callback = &returnsNumber; // Error: incompatible type

The return type and parameter types must match.

Calling a null pointer

FunctionFunc callback = nullptr;
callback(); // Undefined behavior; likely crashes

Check that a pointer was obtained before calling it:

if (callback != nullptr)
{
    callback();
}

Ignoring the calling convention in Windows DLL code

Some Windows APIs and DLL exports use a calling convention such as __stdcall. A mismatch can corrupt the call stack, especially in 32-bit builds.

using FunctionFunc = void (__stdcall *)();

The declaration must match the DLL function exactly. Prefer a shared header supplied by the DLL when one is available.

Unloading a DLL too early

A pointer returned by GetProcAddress points into the loaded DLL. Do not call it after FreeLibrary has unloaded that DLL.

Comparisons

DeclarationMeaning
void run();A function named run that returns void.
void (*runPointer)();A variable that points to a function returning void.
typedef void (*FunctionFunc)();An alias for the type “pointer to a function returning void.”
FunctionFunc runPointer;A function-pointer variable using the alias.
using FunctionFunc = void (*)();Modern C++ spelling of the same type alias.

typedef versus using

Featuretypedefusing
Available in CYesNo
Available in C++YesYes
Function pointer aliastypedef void (*Fn)();using Fn = void (*)();
Typical modern C++ preferenceSupportedUsually preferred for readability

Function pointers versus std::function

FeatureFunction pointerstd::function
Can point toOrdinary compatible functionsFunctions, lambdas, functors, bound calls
OverheadUsually minimalMay have additional overhead
DLL lookup useCommon and appropriateUsually not the direct result type
HeaderNone required<functional>

For direct DLL exports, a raw function pointer is the normal representation because the DLL provides a machine-level function address with a specific signature.

Take Quiz

Cheat Sheet

// Direct declaration
void (*callback)();

// Type alias: C and C++
typedef void (*FunctionFunc)();

// Type alias: modern C++
using FunctionFunc = void (*)();

// Declare a variable
FunctionFunc callback = nullptr;

// Store a compatible function address
void work();
callback = &work;

// Call it
callback();
  • void before (*name) is the return type.
  • () contains the parameter list; empty means no parameters in C++.
  • Parentheses around *name are required.
  • typedef/using creates a type alias, not an object.
  • Match return type, parameter types, and calling convention exactly.
  • Check for nullptr before calling a dynamically obtained function pointer.
  • Do not use a DLL function pointer after unloading its DLL.

FAQ

What does typedef void (*FunctionFunc)(); mean?

It defines FunctionFunc as a type alias for a pointer to a function that takes no arguments and returns void.

Does typedef create a function pointer variable?

No. It creates only a type name. Write FunctionFunc fn = nullptr; to create a variable.

Why is the asterisk inside parentheses?

Without parentheses, C and C++ parse the declaration as a function returning a pointer. (*name) changes the meaning to a pointer to a function.

Is void (*)() an anonymous function?

No. It is a type description. void is the return type, * indicates a pointer, and () describes the function parameters.

Can I assign any function to FunctionFunc?

No. The function must have a compatible signature: no parameters and a void return type. Its calling convention must also match when applicable.

Should I use typedef or using in C++?

Both work. In modern C++, using FunctionFunc = void (*)(); is often easier to read. Use typedef when writing C-compatible declarations or following an existing codebase style.

Why check GetProcAddress before calling the result?

If the DLL does not export that name, GetProcAddress returns nullptr. Calling a null function pointer is invalid and can crash the program.

Why does a DLL function pointer become invalid after FreeLibrary?

The pointer refers to code inside that DLL. Once the DLL is unloaded, that code may no longer be present in memory.

Take Quiz

Mini Project

Description

Build a small callback-based task runner. It stores the address of a no-argument function in a typedef-defined function pointer, validates the pointer, and then runs the selected task. This mirrors the final step of calling a function obtained from a DLL.

Goal

Create and call a void() function pointer through a reusable typedef alias.

Requirements

Requirement 1

Take Quiz

Keep learning

Related questions

View more