Skip to main content
A pointer declaration introduces an identifier as a pointer to a specified data type. It establishes the pointer’s name and the base type of the data it addresses, which dictates pointer arithmetic stride and dereference semantics. While a pointer definition allocates memory for the pointer variable itself, a pure declaration (such as one using the extern keyword) merely informs the compiler of the pointer’s type and identifier without allocating storage.

Basic Syntax

The standard syntax consists of a base type, an asterisk (*) acting as the pointer declarator, and an identifier:
  • type: The base type (e.g., int, char, float, or a struct). This dictates how the compiler interprets the memory at the target address.
  • *: The pointer declarator. In the context of a declaration, it indicates that the identifier is a pointer.
  • identifier: The name of the pointer variable.

Asterisk Binding and Multiple Declarations

In C, the asterisk binds to the identifier, not the base type. This is a critical syntactic rule when declaring multiple variables in a single statement.
Because the asterisk binds to the variable name, idiomatic C style places the asterisk immediately adjacent to the identifier (int *ptr) rather than the type (int* ptr).

Initialization and Storage Duration

The initial value of a pointer declared without an explicit initializer depends strictly on its storage duration:
  • Automatic storage duration: Pointers declared locally without the static keyword are uninitialized and hold an indeterminate value (often called “wild pointers”).
  • Static or thread storage duration: Pointers declared globally, or locally with the static keyword, are implicitly initialized to a null pointer.
When explicitly initializing a pointer to a null pointer constant using the NULL macro, a header defining the macro (such as <stddef.h>) must be included.

Type Qualifiers (const, volatile, restrict)

Pointer declarations can include type qualifiers. The placement of the qualifier strictly defines whether it applies to the pointer itself or the data being pointed to. The rule is read right-to-left: a qualifier applies to whatever is immediately to its left. If there is nothing to its left, it applies to whatever is immediately to its right. const and volatile:
restrict (C99): The restrict qualifier applies exclusively to pointers. It is a promise to the compiler that for the lifetime of the pointer, the memory it addresses is accessed only through that pointer (or pointers derived from it). This allows the compiler to perform aggressive optimizations, such as caching values in registers, by eliminating pointer aliasing concerns.

Complex Pointer Declarations

Pointer declarations can be combined with other declarators to form complex types. The Right-Left Rule (or spiral rule) is used to parse these declarations based on operator precedence. Pointers to Pointers (Multiple Indirection): Requires multiple asterisks, each representing a level of indirection.
Pointers to Arrays: Parentheses are required because the array subscript operator [] has higher precedence than the pointer declarator *.
Pointers to Functions: Parentheses are similarly required because the function call operator () has higher precedence than *.
Tired of Poor C Skills? Fix That With Deep Grasping!Learn More