NULL in C: what it is, how to check for it, and C23 nullptr

By

Tagged: C

NULL in C is the null pointer macro from stdio.h and stddef.h. See how to check a pointer against it, avoid the segfault, and when to use C23's nullptr.

In C, NULL is a macro that represents a null pointer: a pointer that points to nothing. You use it to initialize pointers that don’t have a target yet, and to check if a pointer is safe to use.

Several programming languages make use of the concept of null.

Go has nil, JavaScript has null, Python has None, and so on.

C has NULL.

NULL however is used differently from other languages. In C, NULL is limited to identifying a null pointer. It’s not a general “no value” marker you can assign to an int or a float.

When we initialize a pointer, we might not always know what it points to. That’s when it is useful:

int * p_some_variable = NULL;

Where is NULL defined?

NULL is not available by default: you need to include stdio.h to use it (or if you prefer, stddef.h):

#include <stdio.h>

int main(void) {
  int * p_some_variable = NULL;
}

Other common headers like stdlib.h and string.h define it too, so in practice most programs get it for free.

Otherwise the C compiler will give you an error:

hello.c:3:26: error: use of undeclared identifier
      'NULL'
        int * p_some_variable = NULL;
                                ^
1 error generated.

How to check for a null pointer

You can check if a pointer is a null pointer by comparing it to NULL:

#include <stdio.h>

int main(void) {
  int * p_some_variable = NULL;

  if (p_some_variable == NULL) {
    printf("equal");
  }
}

This check is everywhere in real C code, because many standard library functions return NULL to signal failure. fopen() is a good example. It returns NULL when the file can’t be opened:

#include <stdio.h>

int main(void) {
  FILE *fp = fopen("data.txt", "r");

  if (fp == NULL) {
    printf("could not open data.txt\n");
    return 1;
  }

  fclose(fp);
}

malloc() works the same way: it returns NULL when it can’t allocate memory.

The pitfall: dereferencing NULL

Reading or writing through a null pointer is undefined behavior. On most systems the program crashes with a segmentation fault:

int * p = NULL;
printf("%d\n", *p); /* crash */

The fix is the check we just saw: compare the pointer to NULL before dereferencing it.

NULL is not ‘\0’

Under the hood, NULL is typically defined as ((void *)0) or 0.

Don’t confuse it with '\0', the null character that terminates C strings. They both have the value zero, but NULL is for pointers and '\0' is a char inside a string.

A line like char *a_string = '\0'; compiles, but it does not create an empty string. It sets the pointer to NULL, because '\0' is just the integer zero. An empty string is "", a real (tiny) array containing only the terminator.

C23: nullptr

If you target C23, prefer the nullptr keyword instead of NULL. It converts to any pointer type as a null pointer, and its type is nullptr_t from <stddef.h>.

The problem with NULL is that it can expand to a plain 0. Then _Generic sees an integer, and passing it to a variadic function that reads a pointer is undefined behavior. nullptr always has a pointer meaning.

#include <stddef.h>

int *p = nullptr;
nullptr_t n = nullptr;

Existing code that uses NULL is fine. For new C23 code, nullptr is the clearer choice.

Want me to talk about your product? You can sponsor this site.

Related posts about clang: