Pointers in C Programming

Introduction to Pointers

Suppose a city has a house with an address for each house. You don’t get the house when you know the address, but you do get to know where to find it exactly. In C, pointers are used in the same way. A pointer does not hold a value, it holds the memory address of a variable.

Every variable you declare in C occupies a certain amount of RAM. That space has an address. It has a number, a way to tell you exactly where it is. A pointer is just a variable that contains one of those addresses. 

 

int x = 10;       // ‘x’ holds the value 10
int *ptr = &x;    // ‘ptr’ holds the address of ‘x’

 

Why do pointers matter?

Without pointers, C would be far less powerful. They enable:

  • Passing large data to functions (without copying)
  • Run-time dynamic memory allocation
  • Building data structures like linked lists, and trees
  • Direct programming of hardware and device drivers

Pointer

Fig 1: Variable and Pointer in Memory

 

Understanding Memory and Addresses

RAM is divided into millions of tiny cells that each store one byte of information and are given a unique address. C gives you two operators for dealing with addresses.

 

OperatorName / Meaning
& (Address-of)Returns the memory address of a variable
* (Dereference)Returns the value stored at an address
int x = 10;
int *ptr = &x;

printf("%d\n", x);     // Output: 10       (value of x)
printf("%p\n", &x);    // Output: 0x7FFF04 (address of x)
printf("%d\n", *ptr);  // Output: 10       (value at ptr's address)

  *ptr means “look at the address in ptr and read the value at that address”. This is called dereferencing.

Pointer

Fig 2: Memory Layout

 

Declaring and Initializing Pointers

The ‘*’ symbol is always present in pointer syntax and must match the data type it points to:

 

int   *ip;         // pointer to int
float *fp;         // pointer to float
char  *cp;         // pointer to char
int   *ptr = NULL; // NULL pointer — safe default, points nowhere

 

⚠ Important: Initialise your pointers always. An uninitialized pointer has a garbage address and can crash your program or corrupt memory.

  Pointer

Fig 3: NULL Pointer Representation

  • A NULL pointer says: ‘I am not pointing at anything yet.’
  • Dereferencing NULL causes a segmentation fault — safer than a wild address.

Pointer Arithmetic

The pointers are not normal integers. Adding 1 to a pointer does not necessarily increase its address by 1 byte; the pointer is increased by the size of the type it points to.

 

int arr[5] = {10, 20, 30, 40, 50};
int *ptr = arr;   // ptr points to arr[0]

printf("%d\n", *ptr);   // 10
ptr++;                   // moves forward sizeof(int) = 4 bytes
printf("%d\n", *ptr);   // 20

 

Data TypeSize (typical)ptr++ moves by
char1 byte1 byte
int4 bytes4 bytes
double8 bytes8 bytes

  Pointer

Fig 4: Pointer Traversing an Array

 

Pointers and Arrays

In C programming the name of an array is a pointer to the first element of the array. arr and &arr[0] are the same.

 

int arr[5] = {10, 20, 30, 40, 50};

// These two expressions are equivalent:
printf("%d\n", arr[2]);       // 30
printf("%d\n", *(arr + 2));   // 30

 

Access StyleExample / Meaning
Index notation:    arr[i]Element at index i (compiler sugar)
Pointer arithmetic: *(arr+i)Same element, explicit pointer form

  Pointer

Fig 5: Array Memory Representation

 

Pointers and Functions

By default C passes arguments by value, the function gets a copy. The changes inside the function do not affect the original. Pointers give you call by reference, allowing functions to modify the caller’s variables directly.

 

// Call by value — does NOT swap
void swap_wrong(int a, int b) {
    int temp = a; a = b; b = temp;  // swaps local copies only
}

// Call by reference — DOES swap
void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

// Usage:
int x = 5, y = 10;
swap(&x, &y);
// x is now 10, y is now 5

  Pointer

Fig 6: Swap Function Step-by-Step

 

Pointers and Strings

In C, a string is an array of characters terminated with the null terminator ‘\0’. A char* pointer can walk it character by character.

 

char str[] = "Hello";
char *ptr = str;

while (*ptr != '\0') {
    printf("%c ", *ptr);   // Hello
    ptr++;
}

  Pointer

Fig 7: String Stored in Memory

 

📝 Note: String literals, like “Hello”, are stored in read-only memory. If you need to change the string, use char str[] (array form).

 

Double Pointers (Pointer to Pointer)

A double pointer holds the address of a pointer. This is written in ‘**’.

 

int   x  = 10;
int  *p  = &x;    // p  holds address of x
int **pp = &p;    // pp holds address of p

printf("%d\n",   x);    // 10
printf("%d\n",  *p);    // 10
printf("%d\n", **pp);   // 10

  Pointer

Fig 8: Double Pointer Memory Chain

Double pointers are very common in functions that want to change a pointer itself (e.g. malloc wrappers), and in 2D arrays and arrays of strings.

 

Function Pointers (Advanced)

Just as you can point to data, you can point to functions. A function pointer stores the address of a function and lets you call it indirectly — essential for callbacks, plugin architectures, and embedded systems.

 

int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }

// Declare a function pointer matching the signature
int (*funcPtr)(int, int);

funcPtr = add;
printf("%d\n", funcPtr(3, 4));   // 7

funcPtr = sub;
printf("%d\n", funcPtr(3, 4));   // -1

  Pointer

Fig. 9: Function Pointer Mechanism

Function pointers power callback functions in the C standard library (qsort, bsearch), interrupt service routines in embedded firmware, and virtual function tables in object-oriented C patterns.

 

Common Mistakes and Pitfalls

Pointer

Fig. 10: Common Pointer Errors

 

MistakeBad CodeFix
Uninitialized pointerint *p; *p = 5;int *p = NULL;; then assign
Dangling pointerfree(ptr); *ptr = 5;Set ptr = NULL after free
Memory leakptr = malloc(...); /* no free */Always call free(ptr)
NULL dereferenceint *p = NULL; *p;Check if (p != NULL) first
Wrong type pointerint x; float *p = &x;Match pointer type to variable

 

Practical Applications of Pointers

Pointers are the backbone of systems programming. Here’s where they appear in the real world:

  • Linked Lists & Trees: Each node contains a pointer to the next/child node, enabling dynamic, non-contiguous data structures.
  • Operating Systems: The OS kernel uses pointers to manage process tables, file descriptors, and page tables.
  • Embedded Systems: Microcontroller registers are accessed through fixed memory addresses — pointers let C code read and write hardware directly.
  • Device Drivers: Drivers map hardware I/O ports to memory-mapped addresses, accessed entirely via pointers.
  • VLSI & Hardware Interfacing: Memory-mapped I/O in SoC design uses pointer-like addressing to configure hardware blocks.
  • Sorting & Searching: qsort() in the C standard library takes a function pointer for comparison, making it work with any data type.

Summary

ConceptKey Point
Address operator &Gets the memory address of a variable
Dereference operator *Reads/writes the value at an address
Arrays & Pointersarr[i] is equivalent to *(arr+i); array name = pointer to first element
Pointer ArithmeticAdvances by sizeof the pointed-to type, not by 1 byte
Function PointersStore and call functions dynamically; used in callbacks
Dynamic Memorymalloc/calloc on heap; always free when done
Double PointersPointer to pointer; used in 2D arrays and modifying pointers in functions
Best PracticesInitialize all pointers; check for NULL; free every allocation; set ptr = NULL after free

FAQs

What is a pointer in C programming?

A pointer is a special variable that stores the memory address of another variable instead of storing a direct value. Pointers enable efficient memory management and dynamic data structures in C.

int x = 10;

int *ptr = &x;

Here, ptr stores the address of x.

The address-of operator (&) returns the memory address of a variable.

int x = 10;

printf(“%p”, &x);

The asterisk (*) is used for:

 

  • Declaring a pointer.
  • Dereferencing a pointer.

int *ptr;

printf(“%d”, *ptr);

Dereferencing means accessing the value stored at the memory address held by a pointer.

int x = 10;int *ptr = &x;printf(“%d”, *ptr);

Output:

             10

Syntax:

             data_type *pointer_name;

Example:

int *ptr;float *fptr;char *cptr;

A NULL pointer points to no valid memory location.

             int *ptr = NULL;

It is used to indicate that a pointer is currently not pointing anywhere.

A dangling pointer points to memory that has already been freed.

int *ptr = malloc(sizeof(int));

free(ptr);

After free(), ptr becomes dangling.

The name of an array acts like a constant pointer to its first element.

                          int arr[5];

Equivalent:

                    arr == &arr[0]

Pointer arithmetic allows incrementing or decrementing pointers to move through memory locations.

 

ptr++;

 

The pointer moves by the size of its data type.

Array elements are stored in contiguous memory locations. Incrementing a pointer moves it to the next array element.

int arr[5];

int *ptr = arr;

ptr++;

Answers:

The array name acts as a pointer to the first element of the array.

arr[i]

is equivalent to

*(arr+i)

Yes. Such a pointer is called a double pointer.

int **pp;

Double pointers are commonly used in dynamic memory management and function arguments.

A segmentation fault occurs when a program attempts to access invalid memory, such as dereferencing a NULL or dangling pointer.

Pointers can provide efficient memory access and are often used in performance-critical applications, although modern compilers optimize both approaches effectively.

Strings in C are arrays of characters, and pointers can be used to access and manipulate them efficiently.

char *str = “Hello”;

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top