Pointers

Pointers are a fundamental and powerful feature in C that let you work directly with memory. They can seem a bit tricky at first, but they’re incredibly useful once you get the hang of them.

What is a Pointer?

A pointer is a variable that stores the address of another variable. Instead of holding a data value, a pointer holds the location of that value in memory.

Pointer Basics

  • Declaration: You declare a pointer by specifying the type of data it points to, followed by an asterisk *.

    int *ptr;  // Pointer to an integer
  • Initialization: You assign a pointer the address of a variable using the address-of operator &.

    int x = 10;
    int *ptr = &x;  // 'ptr' now holds the address of 'x'
  • Dereferencing: To access the value stored at the address a pointer points to, you use the dereference operator *.

    int value = *ptr;  // Retrieves the value at the address stored in 'ptr'

Pointer Example

Here’s a simple example showing how pointers work:

#include <stdio.h>

int main() {
    int x = 10;         // Regular integer variable
    int *ptr = &x;      // Pointer variable that holds the address of 'x'
    
    printf("Value of x: %d\n", x);        // Outputs: Value of x: 10
    printf("Address of x: %p\n", &x);    // Outputs the memory address of 'x'
    printf("Value of ptr: %p\n", ptr);   // Outputs the address stored in 'ptr'
    printf("Value pointed to by ptr: %d\n", *ptr);  // Outputs: Value pointed to by ptr: 10
    
    return 0;
}

Explanation:

  • int *ptr = &x; initializes the pointer ptr with the address of x.

  • *ptr is used to access the value of x through the pointer.


Pointer Arithmetic

Pointers can be incremented or decremented to point to different memory locations. This is especially useful with arrays.

Example: Pointer Arithmetic with Arrays

#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30};
    int *ptr = arr;  // Pointer to the first element of the array
    
    printf("First element: %d\n", *ptr);         // Outputs: 10
    printf("Second element: %d\n", *(ptr + 1));  // Outputs: 20
    printf("Third element: %d\n", *(ptr + 2));   // Outputs: 30
    
    return 0;
}

Explanation:

  • ptr + 1 moves the pointer to the next integer (4 bytes away in most systems).

  • *(ptr + 1) accesses the second element of the array.


Dynamic Memory Allocation

Pointers are used to allocate memory dynamically at runtime using functions from the <stdlib.h> library.

Functions:

  • malloc(size_t size): Allocates memory.

  • free(void *ptr): Frees allocated memory.

  • calloc(size_t num, size_t size): Allocates memory and initializes it to zero.

  • realloc(void *ptr, size_t newSize): Resizes previously allocated memory.

Example: Using malloc and free

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *arr = (int *)malloc(3 * sizeof(int));  // Allocate memory for 3 integers
    
    if (arr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }
    
    arr[0] = 10;
    arr[1] = 20;
    arr[2] = 30;
    
    printf("First element: %d\n", arr[0]);   // Outputs: 10
    printf("Second element: %d\n", arr[1]);  // Outputs: 20
    printf("Third element: %d\n", arr[2]);   // Outputs: 30
    
    free(arr);  // Free the allocated memory
    
    return 0;
}

Explanation:

  • malloc allocates memory on the heap.

  • Always check if malloc returns NULL to handle memory allocation failures.

  • free releases the allocated memory to avoid memory leaks.


Pointers and Functions

Pointers can be passed to functions to allow modifications to the original data or to handle large amounts of data efficiently.

Example: Modifying Data Using Pointers

#include <stdio.h>

void increment(int *p) {
    (*p)++;  // Increment the value pointed to by 'p'
}

int main() {
    int num = 5;
    increment(&num);  // Pass the address of 'num'
    printf("Incremented value: %d\n", num);  // Outputs: Incremented value: 6
    return 0;
}

Explanation:

  • increment(&num) passes the address of num to the function.

  • (*p)++ modifies the value of num through the pointer.


Pointers to Pointers

A pointer to a pointer is a variable that stores the address of another pointer.

Example:

#include <stdio.h>

int main() {
    int x = 10;
    int *ptr = &x;
    int **pptr = &ptr;
    
    printf("Value of x: %d\n", x);                // Outputs: 10
    printf("Value pointed to by ptr: %d\n", *ptr); // Outputs: 10
    printf("Value pointed to by pptr: %d\n", **pptr); // Outputs: 10
    
    return 0;
}

Explanation:

  • ptr is a pointer to x.

  • pptr is a pointer to ptr.


Summary

  • Pointers store addresses of variables.

  • Dereferencing * accesses the value at the pointer’s address.

  • Pointer Arithmetic allows moving through arrays.

  • Dynamic Memory Allocation uses malloc, calloc, realloc, and free.

  • Pointers in Functions enable modifications to original data.

  • Pointers to Pointers involve multiple levels of indirection.

Last updated

Was this helpful?