top of page

Pointers and two-dimensional arrays

  • Writer: Siddharth Sharma
    Siddharth Sharma
  • Nov 8, 2024
  • 3 min read

Two-dimensional arrays in C and C++ can be accessed and manipulated using pointers. Two-dimensional arrays are essentially arrays of arrays, which allows for both straightforward array syntax and flexible pointer manipulation.


Basics of Two-Dimensional Arrays

A two-dimensional array is declared with two sets of square brackets:


int arr[3][4];

This creates a 3x4 array, with 3 rows and 4 columns. Each element is stored in contiguous memory, and you can think of it as arr[i][j], where i is the row and j is the column.


Memory Layout of a 2D Array

In memory, a 2D array is stored as a single, contiguous block. For example, in the above 3x4 array, the elements are laid out in memory sequentially, row by row:


arr[0][0], arr[0][1], arr[0][2], arr[0][3],
arr[1][0], arr[1][1], arr[1][2], arr[1][3],
arr[2][0], arr[2][1], arr[2][2], arr[2][3]

Accessing Elements with Pointers

In a two-dimensional array, the array name (arr) is treated as a pointer to the first row (not the first element). arr points to arr[0], which is itself an array of integers.

Here's how to declare a pointer to a 2D array and access elements using pointer arithmetic:

Example: Accessing 2D Array Elements with Pointers


#include <stdio.h>

int main() {
    int arr[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };

    // Accessing elements using traditional array indexing
    printf("arr[1][2] using array indexing: %d\n", arr[1][2]);  // Outputs 7

    // Accessing elements using pointers
    int* ptr = &arr[0][0];  // Pointer to the first element of the 2D array

    printf("arr[1][2] using pointer arithmetic: %d\n", *(ptr + 1 * 4 + 2));  // Outputs 7

    return 0;
}

Explanation:

  • int* ptr = &arr[0][0]; makes ptr point to the first element of the array, arr[0][0].

  • (ptr + i num_columns + j) is used to access arr[i][j] through pointer arithmetic. Here, num_columns is 4 (the number of columns in arr), so ptr + i * 4 + j calculates the memory offset to the desired element.


Output:

arr[1][2] using array indexing: 7
arr[1][2] using pointer arithmetic: 7

Passing a 2D Array to a Function

When you pass a 2D array to a function, you can do so by specifying the size of each dimension after the first one, so the compiler knows how to interpret the memory layout.


#include <stdio.h>

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

int main() {
    int arr[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };

    printArray(arr, 3);  // Pass 2D array and number of rows

    return 0;
}

Explanation:

  • void printArray(int arr[][4], int rows): The function parameter int arr[][4] tells the compiler that each row of the array has 4 elements.

  • The printArray function iterates over the array elements and prints them.


Using Pointers to Pointers with 2D Arrays

A more flexible approach is to use pointers to pointers (int**). This approach is especially useful when dynamically allocating 2D arrays, where each row is allocated independently.

Example: Dynamically Allocating a 2D Array with Double Pointers


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

int main() {
    int rows = 3, cols = 4;
    int** arr = (int**)malloc(rows * sizeof(int*));  // Allocate memory for row pointers

    for (int i = 0; i < rows; i++) {
        arr[i] = (int*)malloc(cols * sizeof(int));  // Allocate memory for each row
        for (int j = 0; j < cols; j++) {
            arr[i][j] = i * cols + j + 1;  // Initialize array with sample values
        }
    }

    // Print the dynamically allocated 2D array
    printf("Dynamically allocated 2D array:\n");
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }

    // Free the allocated memory
    for (int i = 0; i < rows; i++) {
        free(arr[i]);  // Free each row
    }
    free(arr);  // Free the row pointers

    return 0;
}

Explanation:

  • int** arr = (int**)malloc(rows sizeof(int));: Allocates memory for an array of row pointers.

  • arr[i] = (int*)malloc(cols * sizeof(int));: Allocates memory for each row.

  • arr[i][j] = i * cols + j + 1;: Initializes elements in the dynamically allocated 2D array.

  • free(arr[i]); and free(arr);: Deallocates the memory, freeing each row and then the array of pointers.


Summary

  • Direct Access: arr[i][j] can be accessed with (arr + i num_columns + j) or ((arr + i) + j).

  • Passing to Functions: Declare 2D arrays in functions with sizes for dimensions after the first (void func(int arr[][cols])).

  • Dynamic Allocation: Use pointers-to-pointers (int**) for flexible dynamic 2D array allocation.


Pointers and 2D arrays provide powerful tools for efficient data handling and are essential for working with matrices, grids, and other tabular data.

 
 
 

Comments


bottom of page