Learn › C Programming

Pointers

Master pointer basics, pointer arithmetic, and the relationship between arrays and pointers.

Pointer Basics

A pointer is a variable that stores the memory address of another variable. You declare a pointer using the asterisk symbol with the type of value it points to. The address-of operator returns the memory address of a variable, and the dereference operator accesses the value at the address stored in a pointer. Pointers are fundamental to C and enable dynamic memory allocation, efficient array handling, and data structures like linked lists.

#include <stdio.h>

int main(void) {
    int number = 42;
    int *ptr = &number;

    printf("Value of number: %d\n", number);
    printf("Address of number: %p\n", (void *)&number);
    printf("Value of ptr: %p\n", (void *)ptr);
    printf("Value at ptr (*ptr): %d\n", *ptr);

    /* Modify value through pointer */
    *ptr = 100;
    printf("number after *ptr = 100: %d\n", number);

    /* Pointer to pointer */
    int **pptr = &ptr;
    printf("Value at **pptr: %d\n", **pptr);

    return 0;
}

Pointer Arithmetic

Pointer arithmetic allows you to move a pointer forward or backward in memory by a number of elements. When you add one to a pointer it advances by the size of the pointed-to type, not by one byte. This means adding one to an int pointer advances by four bytes on most systems. Pointer arithmetic is the foundation of array traversal in C and is one of the features that makes C both powerful and potentially dangerous if misused.

#include <stdio.h>

int main(void) {
    int arr[] = {10, 20, 30, 40, 50};
    int *ptr = arr;

    printf("Array traversal with pointer arithmetic:\n");
    for (int i = 0; i < 5; i++) {
        printf("*(ptr + %d) = %d, address = %p\n",
               i, *(ptr + i), (void *)(ptr + i));
    }

    /* Difference between pointers */
    int *start = &arr[0];
    int *end = &arr[4];
    printf("\nElements between start and end: %td\n", end - start);

    /* Incrementing a pointer */
    ptr = arr;
    while (ptr <= &arr[4]) {
        printf("%d ", *ptr);
        ptr++;
    }
    printf("\n");

    return 0;
}

Arrays and Pointers

Arrays and pointers are closely related in C. An array name by itself evaluates to a pointer to its first element, which is why arrays can be passed to functions that expect pointers. However arrays and pointers are not identical; an array has a fixed size known at compile time while a pointer is a variable that can be reassigned. The subscript operator on an array is actually defined in terms of pointer arithmetic, so arr[i] is equivalent to *(arr + i).

#include <stdio.h>
#include <string.h>

void reverseArray(int *arr, int size) {
    int *left = arr;
    int *right = arr + size - 1;

    while (left < right) {
        int temp = *left;
        *left = *right;
        *right = temp;
        left++;
        right--;
    }
}

void printArray(const int *arr, int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main(void) {
    int data[] = {5, 12, 8, 3, 19, 7, 1};
    int size = sizeof(data) / sizeof(data[0]);

    printf("Original:  ");
    printArray(data, size);

    reverseArray(data, size);
    printf("Reversed:  ");
    printArray(data, size);

    /* String as char pointer */
    const char *message = "Hello, Pointers!";
    printf("String: %s\n", message);
    printf("First char: %c\n", *message);
    printf("Length: %zu\n", strlen(message));

    return 0;
}

Dynamic Memory Allocation

Dynamic memory allocation lets you request memory from the heap at runtime using malloc, calloc, and realloc. The malloc function allocates a specified number of bytes and returns a pointer to the allocated block. You must always check that the returned pointer is not NULL before using it, and you must free the memory when you are done to prevent memory leaks. Proper memory management is one of the most challenging and important aspects of C programming.

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

int main(void) {
    int n = 5;

    /* Allocate array dynamically */
    int *arr = (int *)malloc(n * sizeof(int));
    if (arr == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        return 1;
    }

    /* Initialize and print */
    for (int i = 0; i < n; i++) {
        arr[i] = (i + 1) * 10;
    }

    printf("Dynamic array: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    /* Resize the array */
    n = 8;
    arr = (int *)realloc(arr, n * sizeof(int));
    if (arr == NULL) {
        fprintf(stderr, "Reallocation failed\n");
        return 1;
    }

    for (int i = 5; i < n; i++) {
        arr[i] = (i + 1) * 10;
    }

    printf("Resized array: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    free(arr);

    return 0;
}

← Functions