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]: 1Element at arr[0][1]: 2Element 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.
- During Declaration:
int arr[2][3] = { {1, 2, 3}, {4, 5, 6}};
- 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 34 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:
- 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;}
- 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
-
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.
-
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.
-
Memory Allocation: The memory for 2D arrays is statically allocated (if declared with fixed dimensions) or dynamically allocated (if created during runtime using
malloc
). -
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 34 5 67 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 parametervoid 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
-
Array Declaration: In the function signature
void print_array(int arr[2][3])
, the parameterarr
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.
- The size of the second dimension (
-
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. -
Function Call: In
main()
, we initialize a 2D arrayarr
with 2 rows and 3 columns and then pass it to theprint_array
function.
Output
1 2 34 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 arrayvoid 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
-
Function Parameter: In the function
print_array(int (*arr)[3], int rows)
, the parameterarr
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.
- The pointer
-
Accessing Array Elements: We use the pointer
arr[i][j]
to access elements of the 2D array, just like with the previous example. -
Function Call: The array
arr
is passed toprint_array
, along with the number of rows (2).
Output
1 2 34 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 arrayvoid 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:
-
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. -
Function Call: We pass the dynamically allocated 2D array
arr
to theprint_array
function, along with the number of rows and columns. -
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 34 5 6