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