Null vs Void vs Dangling Pointer in C: Key Differences and Usage
NULL is a special pointer value indicating it points to nothing, void is a keyword used to specify no data type or no return value, and a dangling pointer is a pointer that points to memory that has been freed or is invalid. They serve different purposes: NULL is safe to check, void defines absence of type, and dangling pointers cause undefined behavior if accessed.Quick Comparison
This table summarizes the key differences between NULL, void, and dangling pointers in C.
| Aspect | NULL | void | Dangling Pointer |
|---|---|---|---|
| Definition | A pointer constant representing no valid address | A keyword indicating no data type or no return value | A pointer pointing to freed or invalid memory |
| Type | Pointer value (usually ((void*)0)) | Type specifier (void type) | Pointer variable with invalid target |
| Usage | To indicate pointer points to nothing | To declare functions with no return or generic pointers | Occurs after memory deallocation or invalid pointer assignment |
| Safety | Safe to compare and check | Not a pointer, so no direct safety concern | Unsafe; accessing causes undefined behavior |
| Example | int *p = NULL; | void func(void); | int *p = malloc(...); free(p); then p is dangling |
Key Differences
NULL in C is a macro representing a pointer that points to no valid memory. It is commonly used to initialize pointers or check if a pointer is valid before use. For example, int *p = NULL; means p points to nothing.
void is a keyword used to specify that a function returns no value (void func(void)) or to declare a generic pointer (void *) that can point to any data type. It is not a pointer value but a type specifier.
A dangling pointer happens when a pointer still holds the address of memory that has been freed or is no longer valid. Using a dangling pointer leads to undefined behavior, crashes, or data corruption. For example, after free(p);, the pointer p becomes dangling if not set to NULL.
Code Comparison
This example shows how NULL is used to safely check a pointer before use.
#include <stdio.h> #include <stdlib.h> int main() { int *ptr = NULL; // pointer initialized to NULL if (ptr == NULL) { printf("Pointer is NULL, safe to use later.\n"); } ptr = malloc(sizeof(int)); if (ptr != NULL) { *ptr = 42; printf("Pointer points to value: %d\n", *ptr); free(ptr); ptr = NULL; // avoid dangling pointer } return 0; }
Dangling Pointer Equivalent
This example shows how a dangling pointer can occur if a pointer is used after freeing its memory.
#include <stdio.h> #include <stdlib.h> int main() { int *ptr = malloc(sizeof(int)); if (ptr == NULL) return 1; *ptr = 100; printf("Value before free: %d\n", *ptr); free(ptr); // memory freed // Dangling pointer: ptr still points to freed memory // Accessing *ptr now is undefined behavior printf("Value after free (dangling): %d\n", *ptr); // unsafe ptr = NULL; // fix dangling pointer return 0; }
When to Use Which
Choose NULL when you want to indicate a pointer does not point to any valid memory and to safely check pointer validity before use. Use void when defining functions that do not return a value or when you need a generic pointer type that can point to any data type.
Avoid dangling pointers by setting pointers to NULL immediately after freeing their memory. Dangling pointers should never be used as they cause unpredictable program behavior and bugs.