Search

8.10 — Null pointers

Just like normal variables, pointers are not initialized when they are instantiated. Unless a value is assigned, a pointer will point to some garbage address by default.

Besides memory addresses, there is one additional value that a pointer can hold: a null value. A null value is a special value that means the pointer is not pointing at anything. A pointer holding a null value is called a null pointer.

Initialization and assignment for null pointers

One way to assign a pointer a null value by initializing or assigning it the literal 0:

When used in a pointer context, integer literal 0 has special meaning, and is the only time you can assign an integer literal to a pointer.

Modern C++ programmers typically don’t use integer literal 0 to represent the null value any more (we’ll talk about this in a moment), but it’s still useful indirectly in one case. When initializing a pointer without a value, the pointer is zero-initialized, which means it gets initialized to a null value:

Best practice

Initialize your pointers to a null value if you’re not giving them another value.

Dereferencing null pointers

In the previous lesson, we noted that dereferencing a garbage pointer would lead to undefined results. Dereferencing a null pointer also results in undefined behavior. In most cases, it will crash your application.

Conceptually, this makes sense. Dereferencing a pointer means “go to the address the pointer is pointing at and access the value there”. A null pointer doesn’t have an address. So when you try to access the value at that address, what should it do?

Accidentally dereferencing null pointers is one of the most common mistakes the C++ programmers make. The good news is that we can guard against this happening.

Pointers and Boolean conversions

If you recall from lessons of yore, integer values will readily convert to Boolean values: an integer value of 0 converts to Boolean value false, and any other integer value converts to Boolean value true.

Similarly, pointers will also readily convert to Boolean values: a null pointer (with address 0) converts to Boolean value false, and a pointer holding any non-zero value converts to Boolean value true.

Therefore, we can use a conditional to test whether a pointer is null or not:

The above program prints:

ptr is a null pointer

The NULL macro

In C++, there is a special preprocessor macro called NULL (defined in the <cstddef> header). This macro was inherited from C, where it is commonly used to indicate a null pointer.

The value of NULL is implementation defined, but is usually defined as the integer constant 0 (or nullptr, which we’ll discuss in a moment).

Rule

Because NULL is a preprocessor macro with an implementation defined value, avoid using NULL.

// Move to the next lesson?

The perils of using 0 (or NULL) for null pointers

Note that the value of 0 isn’t a pointer value (it’s an integer literal), so assigning 0 (or NULL in some cases) to a pointer to denote that the pointer is a null pointer is a little inconsistent. In rare cases, when used as a literal argument, it can even cause problems because the compiler can’t tell whether we mean a null value or the integer value 0.

We haven’t talked about this yet, but it turns out that you can define multiple functions with the same name so long as they take parameters of different types. The compiler can tell which one you want by the arguments passed in.

When using integer value, this can cause problems:

On the author’s machine, this prints:

print(int*): null
print(int): 0
print(int): 0

Note that when passing integer value 0 as a parameter, C++ prefers print(int) over print(int*). This can lead to unexpected results.

In the likely case where NULL is defined as value 0, print(NULL) will call print(int), not print(int*) like you might expect for a null pointer literal.

The nullptr keyword

C++11 introduced a new keyword named nullptr. Much like true and false are keywords that represent Boolean literal values, nullptr is a keyword that represents a null value.

The nullptr keyword should be preferred when explicitly assigning or using a null value (use default initialization when initializing a pointer with a null value):

C++ will implicitly convert nullptr to any pointer type. So in the above example, nullptr is implicitly converted to an integer pointer, and then the value of nullptr is assigned to ptr2 (making ptr2 a null pointer).

Best practice

Use nullptr (instead of 0 or NULL) when you need a null value literal. Prefer default initialization to explicit initialization with nullptr when initializing pointers.

We can also call a function with a nullptr literal, which will match to any parameter that takes a pointer value:

This prints:

print(int*): null
print(int): 0
print(int*): null

std::nullptr_t

One interesting question: if nullptr is handled differently than integer value 0, it must have a different type. What type is nullptr? The answer is that nullptr has type std::nullptr_t (defined in header <cstddef>). std::nullptr_t can only hold one value: nullptr! While this may seem kind of silly, it’s useful in one situation. If we want to write a function that accepts only a nullptr argument, what type do we make the parameter? The answer is std::nullptr_t.

You probably won’t ever need to use this, but it’s good to know, just in case.


8.11 -- Pass by address and return by address
Index
8.9 -- Pointers and const

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">