In C, how would you dynamically allocate a 2 dimensional array of integers with ROWS rows and COLS columns using pointers and malloc, so that you can access elements as arr[i][j]?

Difficulty: Medium

Correct Answer: int **arr = malloc(ROWS * sizeof *arr); for (int i = 0; i < ROWS; i++) { arr[i] = malloc(COLS * sizeof *arr[i]); }

Explanation:


Introduction / Context:
Many C programs need to allocate two dimensional arrays at run time when the number of rows and columns is not known at compile time. This question examines how to correctly allocate such a structure using a pointer to pointer approach so that elements can be accessed with the familiar arr[i][j] syntax. It also highlights common mistakes made when mixing dynamic allocation with multi dimensional indexing.


Given Data / Assumptions:

  • The number of rows is ROWS and the number of columns is COLS, determined at run time.
  • We want to access elements as arr[i][j] where 0 ≤ i < ROWS and 0 ≤ j < COLS.
  • We will use malloc for dynamic allocation and int as the element type.
  • The solution should be portable and standards compliant C.


Concept / Approach:
One common dynamic allocation pattern uses a pointer to pointer int **arr. The first allocation reserves ROWS pointers to rows. Each pointer arr[i] then points to a dynamically allocated block of COLS integers. This layout matches the type int ** and allows arr[i][j] to work, because arr[i] is an int * and arr[i][j] indexes element j within that row. The sizeof operator should be written in a way that does not repeat the type, using sizeof *arr for row pointers and sizeof *arr[i] for row elements.


Step-by-Step Solution:
Step 1: Declare a double pointer: int **arr;. Step 2: Allocate memory for ROWS row pointers using arr = malloc(ROWS * sizeof *arr);. Step 3: For each i from 0 to ROWS - 1, allocate a row using arr[i] = malloc(COLS * sizeof *arr[i]);. Step 4: After these allocations, arr[i] is a valid pointer to COLS integers, so arr[i][j] is legal for all valid indices. Step 5: Remember that later you must free each arr[i] and then free arr to avoid memory leaks.


Verification / Alternative check:
You can reason about the types: arr has type int **, so arr[i] has type int *. That pointer can be passed to functions expecting an array of int, and the expression arr[i][j] is defined as *(arr[i] + j), which is valid because arr[i] points to a block of COLS ints. This confirms that the allocation matches the intended usage. The sizeof *arr idiom further protects the code if the type of arr ever changes.


Why Other Options Are Wrong:
Option B allocates a single flat block but then incorrectly treats arr as if it were int ** and tries to index arr[i], which is invalid because arr points to int, not to int *. Option C uses calloc with the wrong total size and still leaves arr uninitialised as a set of pointers, so arr[i][j] is not meaningful. Option D declares a fixed size array with automatic storage duration, which is not dynamic allocation and does not use malloc at all.


Common Pitfalls:
A common mistake is to allocate ROWS * COLS integers and assign that address directly to int **arr, which breaks the two level pointer model required for arr[i][j]. Another pitfall is to use sizeof(int *) instead of sizeof *arr when allocating row pointers, which can be correct but is more error prone. Always align your allocation pattern with the pointer types you actually use in indexing expressions.


Final Answer:
The correct pattern is int **arr = malloc(ROWS * sizeof *arr); followed by a loop that assigns arr[i] = malloc(COLS * sizeof *arr[i]); so that arr[i][j] can be used safely.

More Questions from Programming

Discussion & Comments

No comments yet. Be the first to comment!
Join Discussion