Two Dimensional Arrays

Constructing a 2 dimensional array using the c notation:

File: "2dim.c"

#include<stdio.h>

#include<stdlib.h>

int main()

{

int** TwoDimArray ;

const int ROW_COUNT = 2 ;

const int COL_COUNT = 3 ;

TwoDimArray = (int**)malloc(sizeof(int*)*ROW_COUNT) ;

for(int i1=0 , k1=1 ; i1<ROW_COUNT ; i1++ )

{

TwoDimArray[i1] = (int*) malloc(sizeof(int)*COL_COUNT) ;

for( int j1=0 ; j1<COL_COUNT ; j1++ )

{

TwoDimArray[i1][j1] = k1++ ;

}

} //for

//print contents using array notation

for(int i1=0 ; i1<ROW_COUNT ; i1++ )

{

for( int j1=0 ; j1<COL_COUNT ; j1++ )

{

printf( "%d " , TwoDimArray[i1][j1] ) ;

}

printf( "\n" ) ;

} //for

printf( "\n" ) ;

//print contents using pointer notation

for(int i1=0 ; i1<ROW_COUNT ; i1++ )

{

for( int j1=0 ; j1<COL_COUNT ; j1++ )

{

printf( "%d " , ( *( (*(TwoDimArray+i1)) + j1 ) ) ) ;

}

printf( "\n" ) ; ;

} //for

printf( "\n" ) ;

for(int i1=0 ; i1<ROW_COUNT ; i1++ )

{

free( TwoDimArray[i1] ) ;

}

free( TwoDimArray ) ;

}

Output:

1 2 3

4 5 6

1 2 3

4 5 6

The following example shows a double pointer array can be passed to a function.

File: "2dim_b.c"

#include<stdio.h>

#include<stdlib.h>

void method1( int** arr1 )

{

printf( "Method1: %d\n" , arr1[0][0] ) ;

}

int main()

{

int** TwoDimArray ;

const int ROW_COUNT = 2 ;

const int COL_COUNT = 3 ;

TwoDimArray = (int**)malloc(sizeof(int*)*ROW_COUNT) ;

for(int i1=0 , k1=1 ; i1<ROW_COUNT ; i1++ )

{

TwoDimArray[i1] = (int*) malloc(sizeof(int)*COL_COUNT) ;

for( int j1=0 ; j1<COL_COUNT ; j1++ )

{

TwoDimArray[i1][j1] = k1++ ;

}

} //for

method1( TwoDimArray ) ;

for(int i1=0 ; i1<ROW_COUNT ; i1++ )

{

free( TwoDimArray[i1] ) ;

}

free( TwoDimArray ) ;

return ( 1 ) ;

}

Output:

0

Notice we did not need to specify the size of the 2 dimensional array when passing it to the method. That's because even though the double pointer functions as a 2 dimensional array it is stored differently in RAM. A normal 2 dimensional array is stored as a contiguous sequence but a set of pointers is stored differently. We have a row of pointers and then each pointer points to another location in memory. When we say "arr1[2][1]" as an example first the the 3rd pointer is fetched with the statement "arr1[2]" . We then take the second element of where this pointer is pointing to ( the block ) . This is different from the 2 dimensional array allocation.

Double pointers are used when passing arguments to a "C" program. The strings passed in the command are passed to the function "main"

File: "2dim_c.c"

#include<stdio.h>

#include<stdlib.h>

int main( int argc, char *argv[] )

{

printf( "%d\n" , argc ) ;

if ( argc > 1 )

{

printf( "%s\n" , argv[0] ) ;

printf( "%s\n" , argv[1] ) ;

}

return ( 1 ) ;

}

Output:

./a.exe first second

Jagged Arrays

It is possible to create a 2 dimensional array with different column lengths.

File: "2dim_d.c"

#include<stdio.h>

#include<stdlib.h>

//Jagged Array

int main()

{

int** TwoDimArray ;

const int ROW_COUNT = 2 ;

int COL_COUNT = 1 ;

TwoDimArray = (int**)malloc(sizeof(int*)*ROW_COUNT) ;

for(int i1=0 , k1=1 ; i1<ROW_COUNT ; i1++, COL_COUNT++ )

{

TwoDimArray[i1] = (int*) malloc(sizeof(int)*COL_COUNT) ;

for( int j1=0 ; j1<COL_COUNT ; j1++ )

{

TwoDimArray[i1][j1] = k1++ ;

}

} //for

//print contents using array notation

for(int i1=0 , COL_COUNT = 1 ; i1<ROW_COUNT ; i1++ , COL_COUNT++ )

{

for( int j1=0 ; j1<COL_COUNT ; j1++ )

{

printf( "%d " , TwoDimArray[i1][j1] ) ;

}

printf( "\n" ) ;

} //for

printf( "\n" ) ;

//print contents using pointer notation

for(int i1=0 , COL_COUNT = 1 ; i1<ROW_COUNT ; i1++, COL_COUNT++ )

{

for( int j1=0 ; j1<COL_COUNT ; j1++ )

{

printf( "%d " , ( *( (*(TwoDimArray+i1)) + j1 ) ) ) ;

}

printf( "\n" ) ; ;

} //for

printf( "\n" ) ;

for(int i1=0 ; i1<ROW_COUNT ; i1++ )

{

free( TwoDimArray[i1] ) ;

}

free( TwoDimArray ) ;

}

Exercises

Ex1:

Explain the below program:

/* What is a pointer */

#include<stdio.h>

#include<stdlib.h>

int main()

{

//Double ptr or an array of pointers

const char* colors[] = { "Red", "Green", "Blue" } ;

printf( "%s\n" , colors[1] ) ;

printf( "%p\n" , ( colors + 1 ) ) ;

printf( "%s\n" , *( colors + 1 ) ) ;

printf( "%c\n" , *( colors[1] ) ) ;

// cout << "----------------" << endl ;

//Green

//0x7ffe25a3ff18

//Green

//G

//Another way

char** colors1 = (char**)malloc( sizeof(char*)*3 ) ;

colors1[0] = "Red" ;

colors1[1] = "Green" ;

colors1[2] = "Blue" ;

printf( "%s\n" , colors[1] ) ;

printf( "%p\n" , ( colors + 1 ) ) ;

printf( "%s\n" , *( colors + 1 ) ) ;

printf( "%c\n" , *( colors[1] ) ) ;

//Can't do this

// colors1[0][0] = 'a' ;

return ( 1 ) ;

}

Output:

Green

0x7ffe25a3ff18

Green

G

----------------

Green

0x12edc28

Green

G