Skip to content

4.2 2-Dimensional Array

A 2D array (two-dimensional array) is essentially an array of arrays. It allows you to store data in a tabular format, i.e., rows and columns. In C, it can be thought of as a matrix or a grid.

A 2D array is declared using two indices: one for the row and one for the column.

2.1 Syntax

data_type array_name[rows][columns];
  • data_type: This specifies the type of data that will be stored in the array (e.g., int, float, char, etc.).
  • array_name: The name of the array.
  • rows: The number of rows in the array.
  • columns: The number of columns in the array.

2.2 Example of Declaring a 2D Array

int arr[3][4];
  • This creates a 2D array named arr with 3 rows and 4 columns.
  • The size of the array will be 3 * 4 = 12 integers, where each integer typically takes 4 bytes of memory (on most systems).

2.3 Accessing and Initializing Elements in a 2D Array

You can access the elements of a 2D array using row and column indices. Array indices in C start from 0, so the first row is arr[0], the first column is arr[][0], and so on.

Example:

#include <stdio.h>
int main() {
// Declaration and initialization of a 2D array
int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
// Accessing elements of the 2D array
printf("Element at arr[0][0]: %d\n", arr[0][0]); // Outputs 1
printf("Element at arr[0][1]: %d\n", arr[0][1]); // Outputs 2
printf("Element at arr[1][2]: %d\n", arr[1][2]); // Outputs 6
return 0;
}

Output:

Element at arr[0][0]: 1
Element at arr[0][1]: 2
Element at arr[1][2]: 6

2.4 2D Array Representation in Memory

Internally, a 2D array is represented in memory as a single block of contiguous memory. In the case of a 3x4 array (int arr[3][4]), the elements are stored like this:

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]

This means the elements arr[0][0], arr[0][1], arr[0][2], etc., are stored in consecutive memory locations.

2.5 Initializations of 2D Arrays

You can initialize a 2D array either during declaration or later in the code.

  1. During Declaration:
int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
  1. Later Initialization:
int arr[2][3];
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
arr[1][0] = 4;
arr[1][1] = 5;
arr[1][2] = 6;

2.6 Iterating Over a 2D Array (Using Loops)

You can use nested loops to iterate over the rows and columns of a 2D array.

#include <stdio.h>
int main() {
int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
// Iterating over the 2D array
for (int i = 0; i < 2; i++) { // Loop through rows
for (int j = 0; j < 3; j++) { // Loop through columns
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}

Output:

1 2 3
4 5 6

2.7 Passing 2D Arrays to Functions

You can pass a 2D array to a function in C. There are two ways to do this:

  1. Passing with Fixed Columns:

If the number of columns is fixed, you can pass the array with its row size and column size.

#include <stdio.h>
void print_2d_array(int arr[2][3]) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main() {
int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
print_2d_array(arr);
return 0;
}
  1. Passing with Pointer Notation:

Alternatively, you can pass a 2D array as a pointer to an array of columns.

#include <stdio.h>
void print_2d_array(int (*arr)[3], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main() {
int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
print_2d_array(arr, 2);
return 0;
}

2.8 Important Concepts of 2D Arrays

  1. Arrays in C are passed by reference, meaning when you pass a 2D array to a function, you are passing the address of the array, not a copy of it.

  2. Array decay: When you pass a 2D array to a function, it decays into a pointer to its first element, but the second dimension (number of columns) must be specified so that the function knows how to access the elements.

  3. Memory Allocation: The memory for 2D arrays is statically allocated (if declared with fixed dimensions) or dynamically allocated (if created during runtime using malloc).

  4. Pointer Arithmetic: You can perform pointer arithmetic to traverse a 2D array. For example, arr[i][j] can also be accessed using *(arr + i * num_columns + j).

2.9 Example of Dynamic Memory Allocation for 2D Arrays

In case you don’t know the size of the array at compile time, you can use dynamic memory allocation with malloc to allocate memory for a 2D array.

#include <stdio.h>
#include <stdlib.h>
int main() {
int rows = 3, cols = 3;
int **arr = (int **)malloc(rows * sizeof(int *)); // Allocate memory for rows
for (int i = 0; i < rows; i++) {
arr[i] = (int *)malloc(cols * sizeof(int)); // Allocate memory for columns
}
// Initializing the 2D array
int value = 1;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
arr[i][j] = value++;
}
}
// Printing the 2D array
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
// Freeing the allocated memory
for (int i = 0; i < rows; i++) {
free(arr[i]); // Free each row
}
free(arr); // Free the pointer array
return 0;
}

Output:

1 2 3
4 5 6
7 8 9

2.10 Passing 2D Arrays to Functions

Here’s an example of how you can pass a 2D array to a function in C. We’ll cover both the basic way to pass a 2D array and also how you can handle it using pointers.

1. Example 1: Passing a 2D Array to a Function

Define a 2D array and write a function that takes a 2D array as a parameter to print its elements.

#include <stdio.h>
// Function that takes a 2D array as parameter
void print_array(int arr[2][3]) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main() {
// 2D array initialization
int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
// Passing the 2D array to the function
print_array(arr);
return 0;
}

Explanation

  1. Array Declaration: In the function signature void print_array(int arr[2][3]), the parameter arr represents a 2D array with 2 rows and 3 columns.

    • The size of the second dimension (3 in this case) is necessary when passing the array to the function, as C needs to know how many columns there are in each row to properly index the array.
  2. Accessing Elements: Inside the function, we loop through the rows and columns of the 2D array, using the indexes arr[i][j] to access and print each element.

  3. Function Call: In main(), we initialize a 2D array arr with 2 rows and 3 columns and then pass it to the print_array function.

Output

1 2 3
4 5 6

2. Example 2: Passing a 2D Array Using Pointers

You can also pass a 2D array using a pointer, which may be more flexible when working with dynamically allocated arrays or larger dimensions.

#include <stdio.h>
// Function that takes a pointer to a 2D array
void print_array(int (*arr)[3], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main() {
// 2D array initialization
int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
// Passing the 2D array to the function
print_array(arr, 2);
return 0;
}

Explanation

  1. Function Parameter: In the function print_array(int (*arr)[3], int rows), the parameter arr is a pointer to an array of 3 integers. This allows us to pass the 2D array as a pointer while keeping the ability to reference individual elements using array notation.

    • The pointer arr holds the address of the first row of the 2D array, and each row is an array of 3 integers.
  2. Accessing Array Elements: We use the pointer arr[i][j] to access elements of the 2D array, just like with the previous example.

  3. Function Call: The array arr is passed to print_array, along with the number of rows (2).

Output

1 2 3
4 5 6

3. Example 3: Using Dynamic Memory Allocation for a 2D Array

If you want to use dynamic memory allocation for a 2D array, here’s an example where we dynamically allocate memory for the array and pass it to a function.

#include <stdio.h>
#include <stdlib.h>
// Function that takes a dynamically allocated 2D array
void print_array(int **arr, int rows, int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main() {
int rows = 2, cols = 3;
// Dynamically allocating memory for a 2D array
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 columns
}
// Initializing the array
int value = 1;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
arr[i][j] = value++;
}
}
// Passing the dynamically allocated array to the function
print_array(arr, rows, cols);
// Freeing the dynamically allocated memory
for (int i = 0; i < rows; i++) {
free(arr[i]); // Free each row
}
free(arr); // Free the array of row pointers
return 0;
}

Explanation:

  1. Dynamic Memory Allocation: We use malloc to dynamically allocate memory for a 2D array. First, we allocate memory for the row pointers, and then for each row, we allocate memory for the columns.

  2. Function Call: We pass the dynamically allocated 2D array arr to the print_array function, along with the number of rows and columns.

  3. Freeing Memory: After we’re done using the dynamically allocated memory, we free the memory for each row and then free the array of row pointers to prevent memory leaks.

Output

1 2 3
4 5 6