Skip to Content
Course content

242: The nullptr Constant

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Imagine you're managing a restaurant. You have a dozen tables, and each table is meant to hold a party of guests. Now, if a table is currently empty, you don't just leave it blank—because a blank table looks like it's ready for anyone to sit down. Instead, you place a "Reserved" sign on it. That sign isn't a guest, and it's not a piece of food; it's a specific marker that tells your staff, "There is intentionally nobody here right now."

In C, nullptr is that "Reserved" sign. For a long time, we used NULL or just the number 0 to indicate that a pointer wasn't pointing to anything useful. But the problem with 0 is that it's an integer. If you have a function that can take either an integer or a pointer, the compiler might get confused about whether you're passing the number zero or a null pointer. nullptr solves this by being a distinct type that says, "I am definitely a pointer, and I am definitely pointing to nothing."

Why we stopped just using zero

If you've looked at older C code, you'll see NULL everywhere. In most implementations, NULL is just a macro for ((void*)0). While that worked for decades, it's a bit clunky. By introducing nullptr (starting in C23), the language finally gives us a first-class keyword that the compiler understands natively.

I've spent way too many hours debugging "ambiguous overload" style issues where the compiler thought I was passing an int when I actually meant "no object." Using nullptr removes that ambiguity. It's type-safe. When you see nullptr, you know exactly what's happening: the pointer is intentionally empty.

Putting it into practice

Let's look at a scenario where this is actually useful. Suppose you're writing a function to find a specific user in a list. If the user doesn't exist, you can't return a valid user pointer, so you return nullptr.

struct User {
    int id;
    char name[50];
};

struct User* find_user_by_id(struct User* list, int size, int target_id) {
    for (int i = 0; i < size; i++) {
        if (list[i].id == target_id) {
            return &list[i]; // Found them!
        }
    }
    // We searched the whole list and found nothing.
    // Return nullptr to explicitly say "Not Found".
    return nullptr; 
}

int main() {
    struct User users[] = {{1, "Alice"}, {2, "Bob"}};
    struct User* result = find_user_by_id(users, 2, 99);

    if (result == nullptr) {
        // This is the "Reserved" sign. We know there's no user here.
        printf("User not found.\n");
    } else {
        printf("Found: %s\n", result->name);
    }
    return 0;
}

The logic of the null check

You'll notice the if (result == nullptr) check. This is the most critical part of working with pointers. If you tried to access result->name without checking if result was nullptr first, the program would attempt to read memory at address zero, and the OS would immediately kill your process with a Segmentation Fault. I've crashed more programs in my early career by forgetting this check than I care to admit. Always check for nullptr before dereferencing.




📋 Practical Task

The Missing Employee Lookup

You are building a small HR system. You have a function called get_employee_by_role that should search an array of employees and return a pointer to the one matching a specific role (e.g., "Manager"). If no one has that role, the function must return nullptr.

Your Task: Complete the code below. Implement the get_employee_by_role function to iterate through the array and return the correct pointer or nullptr. In main, ensure you handle the nullptr case so the program doesn't crash when a role is not found.

#include <stdio.h>
#include <string.h>

struct Employee {
    int id;
    char role[20];
};

struct Employee* get_employee_by_role(struct Employee* staff, int count, const char* target_role) {
    // TODO: Implement search logic
    // Return the pointer to the employee if found, otherwise return nullptr
}

int main() {
    struct Employee staff[] = {
        {101, "Developer"},
        {102, "Designer"},
        {103, "Developer"}
    };

    const char* search_role = "CEO"; // This role doesn't exist in our list
    struct Employee* emp = get_employee_by_role(staff, 3, search_role);

    // TODO: Check if emp is nullptr before printing
    // If it is nullptr, print "No employee found with that role."
    // Otherwise, print the employee's ID.

    return 0;
}
Rating
0 0

There are no comments for now.

to be the first to leave a comment.