Search

10.9 — Null pointers

Null values and 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.

In C++, we can assign a pointer a null value by initializing or assigning it the literal 0:

Pointers convert to boolean false if they are null, and boolean true if they are non-null. Therefore, we can use a conditional to test whether a pointer is null or not:

Best practice

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

Indirection through null pointers

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

Conceptually, this makes sense. Indirection through 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?

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. Note: as of C++11, NULL can be defined as nullptr instead (which we’ll discuss in a bit).

Best practice

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

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

Note that the value of 0 isn’t a pointer type, so assigning 0 (or NULL, pre-C++11) 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 pointer or the integer 0:

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.

nullptr in C++11

To address the above issues, C++11 introduces a new keyword called nullptr. nullptr is a keyword, much like the boolean keywords true and false are.

Starting with C++11, this should be favored instead of 0 when we want a null pointer:

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 assigned to ptr. This has the effect of making integer pointer ptr a null pointer.

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

Best practice

Use nullptr to initialize your pointers to a null value.

std::nullptr_t

C++11 also introduces a new type called std::nullptr_t (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.


10.10 -- Pointers and arrays
Index
10.8 -- Introduction to pointers

105 comments to 10.9 — Null pointers

  • Anonymous

    > For advanced readers

    > A function with a different parameter list is a new function, even if a function with the same name exists. We cover this later (Function overloading).

    ...but function overloading is already covered now in a previous chapter, chapter 8!

  • Btw gyz i was thinking that since u gyz didn't mentioned here that nullptr is pointing to a constant memory reference (or something like that) i just thought that since the pointer is pointing at nothing i want to make it point at something so i was writing a function to do that but it said segmentation fault so if someone else tries to try something like this bcz it does makes sense right if the pointer is pointing at nothing we should be able to make it point at some address and u gyz didn't said anything about it so i think u gyz should mention this. And sorry for kinda bad english.

  • Tobito

    std::srand(static_cast<unsigned int>(std::time(nullptr))
    std::srand(static_cast<unsigned int>(std::time(Null))

    All these two can compile successfully, what should i use?

  • James C

    Best practice marked as "Rule"

  • Ladyoftheroundtable

    You wanted us to point out when you did type *name versus type* name and this chapter is rife with it. And does make the code surprisingly difficult to read.

  • haji soetarman

    hey, Nascardriver and Alex! I just wanna point out some perhaps minor inconcistency on this subchapter.

    According to a "Best Practice" section on the previous subchapter, we should better "put the asterisk next to the type to make it easier to distinguish it from an indirection" every time we need to declare a pointer variable. But all the asterisks of the pointer variables here are actually on the next of the variable name.

    Maybe perhaps you can revise this subchapter a little bit.
    Thank you very much....

  • yeokaiwei

    Feedback.

    Is there a page of all the best practices?

    Instead of going to every single page for the best practices.

    Could we have an appendix called "Best Practices" that compiles all the best practices?

Leave a Comment

Put all code inside code tags: [code]your code here[/code]