Menu
Coddy logo textTech

Function Pointers in Structs

Part of the Object Oriented Programming section of Coddy's C journey — lesson 38 of 61.

Until now, we've used function pointers as standalone variables or passed them as arguments. The next step toward polymorphism is embedding a function pointer directly inside a struct — giving the struct its own behavior.

When a struct contains a function pointer, each instance can hold a different function. This means two objects of the same type can behave differently when you call their function pointer:

typedef void (*PrintFunc)(const char*);

typedef struct {
    const char* name;
    PrintFunc print;  // Function pointer as a member
} Printer;

The Printer struct now has two members: data (name) and behavior (print). To use it, you assign a function to the pointer during initialization:

void loud_print(const char* msg) {
    printf("!!! %s !!!\n", msg);
}

int main() {
    Printer p;
    p.name = "Alert";
    p.print = loud_print;
    
    p.print("Hello");  // Output: !!! Hello !!!
    return 0;
}

Notice how we call the function through the struct: p.print("Hello"). This looks remarkably like calling a method on an object in other languages. The struct carries both its data and the function that operates on it.

This pattern is the foundation of polymorphism in C — different instances can have different functions assigned, producing different behaviors from the same struct type.

challenge icon

Challenge

Easy

Let's build a Notifier system that demonstrates how structs can carry their own behavior through function pointers.

You'll create two files to organize your code:

  • notifier.h: Define a function pointer type called NotifyFunc that takes a const char* parameter and returns nothing. Then define a Notifier struct that contains a name (a const char*) and a notify function pointer of type NotifyFunc.
  • main.c: Include your header and implement two notification functions:
    • alert_notify — prints the message in the format: [ALERT] message
    • info_notify — prints the message in the format: [INFO] message
    Then create a Notifier instance, wire up the appropriate function based on input, and call the notification through the struct's function pointer.

Your program will receive two inputs: a notification type (1 for alert, 2 for info) and a message to display.

Based on the type, assign the corresponding function to your notifier's notify member, then call it through the struct to display the message.

Example output when type is 1 and message is "System starting":

[ALERT] System starting

Example output when type is 2 and message is "All systems normal":

[INFO] All systems normal

Remember to use include guards in your header file, and call the function through the struct member: n.notify(message)

Cheat sheet

Function pointers can be embedded directly inside structs, giving each instance its own behavior. This is a foundation for polymorphism in C.

Defining a Struct with a Function Pointer

First, define a function pointer type, then include it as a struct member:

typedef void (*PrintFunc)(const char*);

typedef struct {
    const char* name;
    PrintFunc print;  // Function pointer as a member
} Printer;

Using the Struct

Assign a function to the pointer during initialization, then call it through the struct:

void loud_print(const char* msg) {
    printf("!!! %s !!!\n", msg);
}

int main() {
    Printer p;
    p.name = "Alert";
    p.print = loud_print;
    
    p.print("Hello");  // Output: !!! Hello !!!
    return 0;
}

The syntax p.print("Hello") calls the function through the struct, similar to calling a method on an object in other languages.

Polymorphic Behavior

Different instances of the same struct type can have different functions assigned, producing different behaviors from the same struct type.

Try it yourself

#include <stdio.h>
#include "notifier.h"

// TODO: Implement alert_notify function
// Should print: [ALERT] message


// TODO: Implement info_notify function
// Should print: [INFO] message


int main() {
    int type;
    char message[256];
    
    // Read input
    scanf("%d", &type);
    getchar(); // consume newline
    fgets(message, sizeof(message), stdin);
    
    // Remove trailing newline from message if present
    int len = 0;
    while (message[len] != '\0') len++;
    if (len > 0 && message[len-1] == '\n') message[len-1] = '\0';
    
    // TODO: Create a Notifier instance
    
    
    // TODO: Based on type (1 for alert, 2 for info),
    // assign the appropriate function to the notifier's notify member
    
    
    // TODO: Call the notification through the struct's function pointer
    // Use: n.notify(message)
    
    
    return 0;
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming