A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
NULL is a macro that expands to a null pointer constant, typically (void *)0 or just 0. A null pointer points to nothing. It is the C equivalent of "no value." Every pointer-returning function uses it to signal failure: fopen returns NULL, malloc returns NULL, getenv returns NULL. Checking for NULL before dereferencing is the single most important defensive habit in C. Skip it and you segfault. Or worse, you do not segfault and corrupt data silently.
#include <stdio.h>#include <stdlib.h>int main(void) {int *p = NULL;printf("p = %p\n", (void *)p);if (p == NULL) {printf("Pointer is NULL. Not dereferencing.\n");}printf("About to dereference NULL...\n");fflush(stdout);printf("Value: %d\n", *p);return 0;}
Address zero is not mapped in normal user-space processes. The CPU tries to read from it, the memory management unit sees an unmapped page, and the OS delivers SIGSEGV. This is the good outcome. It crashes immediately at the exact line. The bad outcome is a pointer that is not NULL but points to freed or invalid memory. That one does not crash. It corrupts.
#include <stdio.h>#include <stdlib.h>int main(void) {int *arr = malloc(100 * sizeof(int));if (arr == NULL) {fprintf(stderr, "Allocation failed. Cannot continue.\n");return 1;}arr[0] = 42;printf("arr[0] = %d\n", arr[0]);free(arr);arr = NULL;if (arr == NULL) {printf("Pointer safely nullified after free.\n");}return 0;}
Two habits in that code. Check the return of malloc before using the pointer. Set the pointer to NULL after free. The first prevents dereferencing a failed allocation. The second turns a potential use-after-free into a deterministic NULL dereference if you accidentally access it later. Deterministic crashes are debuggable. Silent corruption is not.
In C, NULL is typically (void *)0. Assigning 0 to a pointer also produces a null pointer; the compiler converts the integer constant 0 to a null pointer in pointer contexts. C23 introduces nullptr as a keyword, borrowed from C++, which has a dedicated type. In pre-C23 code, use NULL for clarity. It communicates intent better than a bare 0.
NULL is your first line of defense. Check it after every allocation, every fopen, every function that returns a pointer. Make it a reflex. The five seconds it takes to write if (p == NULL) saves hours of debugging. Next: void pointers, the generic pointer type that underlies malloc, memcpy, and every type-agnostic C API.
Finish the lesson once you have worked through the material. This awards ★ 20 XP.