C Programming

2D Array

A Two-dimensional (2D) array is an array of one dimensional (1D) arrays. The 1D array sizes are equal. The 2D array is also called a matrix with rows and columns.

Let’s see the following example:

These 3 1D arrays can be represented as a 2D array as follows:

Let’s see another example:

These 3 1D arrays cannot be representing as a 2D array because the sizes of the arrays are different.

Declaration of 2D array

data-type array-name[ROW][COL]

  • Data-type is the data type of the array elements.
  • Array-name is the name of the array.
  • Two subscripts represent the number of rows and columns of the array. The total number of elements of the array will be ROW*COL.

int a[2][3];

Using the above C code, we can declare an integer array, a of size 2*3 (2 Rows and 3 Columns).

char b[3][2];

Using the above C code, we can declare a character array, b of size 2*3 (3 Rows and 2 Columns).

Initialization of 2D array

We can initialize during declaration in following ways:

  1. int a[3][2] = {1,2,3,4,5,6};
  2. int a[][2] = {1,2,3,4,5,6};
  3. int a[3][2] = {{1, 2},{3, 4},{5, 6}};
  4. int a[][2] = {{1, 2},{3, 4},{5, 6}};

Note that in 2 and 4 we have not mentioned the 1st subscript. The C compiler automatically calculates number of rows from the number of elements. But the 2nd subscript must be specified. Following initializations are invalid:

  1. int a[3][] = {1,2,3,4,5,6};
  2. int a[][] = {1,2,3,4,5,6};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//Example1.c  
#include  
#define ROW 3  
#define COL 2  
 
int main()  
{  
    int i,j;  
    int a[ROW][COL] = {  
        {1,2},  
        {3,4},  
        {5,6}  
    };  
     
    printf("Row wise Elements of the array a are :\n");  
     
    for(i=0;i<ROW;i++)  
    {  
        printf("Row %d:",i);  
        for(j=0;j<COL;j++)  
        {  
            printf(" %d",a[i][j]);  
        }  
        printf("\n");  
    }    
     
    printf("\n\nColumn wise Elements of the array a are :\n");  
     
    for(i=0;i<COL;i++)  
    {  
        printf("Column %d:",i);  
        for(j=0;j<ROW;j++)  
        {  
            printf(" %d",a[j][i]);  
        }  
        printf("\n");  
    }  
     
    return 0;  
}

In Example1.c, we have declared an integer array of size 3*2 and initialized. To access array elements, we use two for loop.

To access row-wise, the outer loop is for rows, and the inner loop is for columns.

To access column-wise, the outer loop is for columns, and the inner loop is for rows.

Note that when we declare a 2D array, we use a[2][3], which means 2 rows and 3 columns. Array indexing starts from 0. To access the 2nd row and 3rd column, we have to use the notation a[1][2].

Memory mapping of a 2D array

The logical view of an array a[3][2] may be as follows:

Computer memory is a 1D sequence of bytes. In C language, a 2D array store in the memory in row-major order. Some other programming languages (e.g., FORTRAN), it stores in column-major order in the memory.

Pointer Arithmetic of a 2D array

To understand the pointer arithmetic of the 2D array, first, have a look at the 1D array.

Consider a 1D array:

In 1D array, a is a constant, and its value is the address of the 0th location of the array a[5]. Value of a+1 is the address of the 1st location of the array a[5].  a+i is the address of the ith location of the array.

If we increment a by 1, it is incremented by the size of the data type.

a[1] is equivalent to *(a+1)

a[2] is equivalent to *(a+2)

a[i] is equivalent to *(a+i)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Example2.c  
#include  
#define ROW 3  
#define COL 2  
 
int main()  
{  
    int a[5]={10,20,30,40,50};  
 
    printf("sizeof(int): %ld\n\n",sizeof(int));  
 
    printf("a: %p\n",a);  
    printf("a+1: %p\n",a+1);  
    printf("a+2: %p\n\n",a+2);  
 
    printf("a[1]: %d,  *(a+1): %d\n",a[1],*(a+1));  
    printf("a[2]: %d,  *(a+2): %d\n",a[1],*(a+1));  
    printf("a[3]: %d,  *(a+3): %d\n",a[1],*(a+1));  
     
    return 0;  
}

In Example2.c, the memory address is showing in hexadecimal. The difference between a and a+1 is 4, which is the size of an integer in bytes.

Now, consider a 2D array:

b is a pointer of type: int[ ][4] or int(*)[4]

int[ ][4] is a row of 4 integer. If we increment b by 1, it is incremented by the size of the row.

b is the address of the 0th row.

b+1 is the address of the 1st row.

b+i is the address of ith row.

The size of a row is: ( Number of column * sizeof(data-type)) bytes

Size of a row of an integer array b[3][4] is: 4 * sizeof(int) = 4 * 4 = 16 bytes

A row of a 2D array may be viewed as a 1D array. b is the address of the 0th row. So, we get the following

  • *b+1 is the address of the 1st element of the 0th
  • *b+j is the address of the jth element of the 0th
  • *(b+i) is the address of the 0th element of the ith
  • *(b+i)+j is the address of the jth element of the ith
  • b[0][0] is equivalent to **b
  • b[0][1] is equivalent to *(*b+1)
  • b[1][0] is equivalent to *(*(b+1))
  • b[1][1] is equivalent to *(*(b+1)+1)
  • b[i][j] is equivalent to *(*(b+i)+j)

Address of b[i][j]: b + sizeof(data-type) * ( Number of column * i + j)

Consider a 2D array: int b[3][4]

Address of b[2][1] is : b + sizeof(int) * (4*2 + 1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//Example3.c  
#include  
#define ROW 3  
#define COL 4  
 
int main()  
{  
    int i,j;  
    int b[ROW][COL] = {  
        {10,20,30,40},  
        {50,60,70,80},  
        {90,100,110,120}  
    };  
     
    printf("sizeof(int): %ld\n",sizeof(int));  
    printf("Size of a row: %ld\n",COL*sizeof(int));  
    printf("b: %p\n",b);  
    printf("b+1: %p\n",b+1);  
    printf("b+2: %p\n",b+2);  
    printf("*b: %p\n",*b);  
    printf("*b+1: %p\n",*b+1);  
    printf("*b+2: %p\n",*b+2);  
    printf("b[0][0]: %d    **b: %d\n",b[0][0],**b);  
    printf("b[0][1]: %d    *(*b+1): %d\n",b[0][1],*(*b+1));  
    printf("b[0][2]: %d    *(*b+2): %d\n",b[0][2],*(*b+2));  
    printf("b[1][0]: %d    *(*(b+1)): %d\n",b[1][0],*(*(b+1)));  
    printf("b[1][1]: %d    *(*(b+1)+1): %d\n",b[1][1],*(*(b+1)+1));  
     
    return 0;  
}

In Example3.c, we have seen that size of a row is 16 in decimal notation. The difference between b+1 and b is 10 in hexadecimal. 10 in hexadecimal is equivalent to 16 in decimal.

Conclusion

So, in this article, we have learned about

  1. Declaration of 2D array
  2. Initialization of 2D array
  3. Memory mapping of 2D array
  4. Pointer Arithmetic of 2D array

Now we can use 2D array in our C program without any doubt,

References

Credit for some ideas in this work were inspired by the course, Pointers and 2-D Arrays, by Palash Dey Department of Computer Science & Engg. Indian Institute of Technology Kharagpur

About the author

Bamdeb Ghosh

Bamdeb Ghosh

Bamdeb Ghosh is having hands-on experience in Wireless networking domain.He's an expert in Wireshark capture analysis on Wireless or Wired Networking along with knowledge of Android, Bluetooth, Linux commands and python. Follow his site: wifisharks.com