Functions and Integer Double Dimension Array

In this section, you are going to learn

What are the calling conventions of integer double dimension array ?

Call by Value

Call by Reference

int array_name[Row][Column];

Consider a integer double dimension array

int a[3][4];

Let us answer few basic questions in this array

If fun(x) is the function call, then fun(typeof(x)) is the prototype / definition

Function Call

Function Definition

Observations

fun(a[0][0])

void fun(int x) {}

  • Call by Value

fun(a[1][0])

void fun(int x) {}

  • Call by Value

fun(a[2][0])

void fun(int x) {}

  • Call by Value

fun(&a[0][0])

void fun(int *p) { }

  • Call by Reference

fun(&a[1][0])

void fun(int *p) { }

  • Call by Reference

fun(&a[2][0])

void fun(int *p) { }

  • Call by Reference

fun(**a)

void fun(int x) {}

  • Call by Value

fun(*(*(a + 1) + 0))

void fun(int x) {}

  • Call by Value

fun(*(*(a + 2) + 0))

void fun(int x) {}

  • Call by Value

fun(a[0])

void fun(int *p) { }

  • Call by Reference

fun(a[1])

void fun(int *p) { }

  • Call by Reference

fun(a[2])

void fun(int *p) { }

  • Call by Reference

fun(&a[0])

void fun(int (*p)[4]) { }

  • Call by Reference

fun(&a[1])

void fun(int (*p)[4]) { }

  • Call by Reference

fun(&a[2])

void fun(int (*p)[4]) { }

  • Call by Reference

fun(*a)

void fun(int *p) { }

  • Call by Reference

fun(*(a + 1))

void fun(int *p) { }

  • Call by Reference

fun(*(a + 2))

void fun(int *p) { }

  • Call by Reference

fun(a)

void fun(int (*p)[4]) { }

  • Call by Reference

fun(a + 1)

void fun(int (*p)[4]) { }

  • Call by Reference

fun(a + 2)

void fun(int (*p)[4]) { }

  • Call by Reference

fun(&a)

void fun(int (*p)[3][4]) { }

  • Call by Reference

Let us understand the reason behind above prototypes !

If Declaration has two dereference operators, and

  • Expression has two dereference operators [] [], and

  • Expression does not have &

  • then it is call by value

If Declaration has two dereference operators, and

  • Expression has two dereference operators * *, and

  • Expression does not have &

  • then it is call by value

If Declaration has two dereference operators, and

  • Expression has two dereference operators * [ ], and

  • Expression does not have &

  • then it is call by value

Let us look at examples

  • Step 1 : Consider an array

int a[3][4] = {
        {1, 2, 3, 4},
        {10, 20, 30, 40},
        {100, 200, 300, 400}
};

Condition 1 : Declaration has TWO dereference operators [ ] and [ ]

  • Step 2 : Consider an expression a[1][1]

Condition 2 : Expression has TWO dereference operators [ ] and [ ]

Note : [ ] and * are dereference operators

Condition 3 : Expression DOES NOT have & operator

Hence a[1][1] is Call By Value

  • Step 1 : Consider an array

int a[3][4] = {
        {1, 2, 3, 4},
        {10, 20, 30, 40},
        {100, 200, 300, 400}
};

Condition 1 : Declaration has TWO dereference operators [ ] and [ ]

  • Step 2 : Consider an expression **a

Condition 2 : Expression has TWO dereference operators * and *

Note : [ ] and * are dereference operators

Condition 3 : Expression DOES NOT have & operator

Hence **a is Call By Value

If Declaration has two dereference operators, and

  • Expression has two dereference operators [] [] or * * or [] *, and

  • Expression has &

  • then it is call by reference

  • Example : &a[0][0]

If Declaration has two dereference operators, and

  • Expression has one dereference operator [ ] or *, and

  • then it is call by reference

  • Example : &a[0], a[0], *a

If Declaration has two dereference operators, and

  • Expression has zero dereference operators, and

  • then it is call by reference

  • Example : a, &a, a + 1, a + 2

  • Step 1 : Consider an array

int a[3][4] = {
        {1, 2, 3, 4},
        {10, 20, 30, 40},
        {100, 200, 300, 400}
};

Condition 1 : Declaration has TWO dereference operators [ ] and [ ]

  • Step 2 : Consider an expression &a[1][1]

Condition 2 : Expression has TWO dereference operators * and *

Note : [ ] and * are dereference operators

Condition 3 : Expression has & operator

Hence &a[1][1] is Call By Reference

  • Step 1 : Consider an array

int a[3][4] = {
        {1, 2, 3, 4},
        {10, 20, 30, 40},
        {100, 200, 300, 400}
};

Condition 1 : Declaration has TWO dereference operators [ ] and [ ]

  • Step 2 : Consider an expression a[1]

Condition 2 : Expression has ONE dereference operators

Note : [ ] and * are dereference operators

Condition 3 : Expression DOES NOT have & operator

Hence a[1] is Call By Reference

Let us look at examples of Call by Value

  • Step 1 : Consider a two dimensional array

int a[3][4] = {
        {1, 2, 3, 4},
        {10, 20, 30, 40},
        {100, 200, 300, 400}
};
  • Step 2 : Pass a[0][0], a[1][0], a[1][1] to a function fun

fun(a[0][0]);

fun(a[1][0]);

fun(a[1][1]);
  • Step 3 : Define function fun

void fun(int c)
{
        printf("c = %d\n", c);

        c = 99;
}
  • Step 4 : Note that it is call by Value for below reason

Condition 1 : Declaration has TWO dereference operators [ ] and [ ]

Condition 2 : Expression has TWO dereference operators [ ] and [ ]

Condition 3 : Expression DOES NOT have & operator

Means changing value of integer inside function DOES NOT affect value of integer in Caller !

  • See full program below

#include <stdio.h>

void fun(int c)
{
        c = 99;
}

int main(void)
{
        int a[3][4] = {
                {1, 2, 3, 4},
                {10, 20, 30, 40},
                {100, 200, 300, 400}
        };

        printf("----- Before call by value -----\n");
        printf("a[0][0] = %d\n", a[0][0]);
        printf("a[1][0] = %d\n", a[1][0]);
        printf("a[1][1] = %d\n", a[1][1]);

        fun(a[0][0]);

        fun(a[1][0]);

        fun(a[1][1]);

        printf("----- After call by value -----\n");
        printf("a[0][0] = %d\n", a[0][0]);
        printf("a[1][0] = %d\n", a[1][0]);
        printf("a[1][1] = %d\n", a[1][1]);

        return 0;
}
  • Output is as below

----- Before call by value -----
a[0][0] = 1
a[1][0] = 10
a[1][1] = 20

----- After call by value -----
a[0][0] = 1
a[1][0] = 10
a[1][1] = 20
  • Step 1 : Consider a two dimensional array

int a[3][4] = {
        {1, 2, 3, 4},
        {10, 20, 30, 40},
        {100, 200, 300, 400}
};
  • Step 2 : Pass **a, *(*(a + 1) + 0), *(*(a + 1) + 1) to a function fun

fun( **a );

fun( *(*(a + 1) + 0) );

fun( *(*(a + 1) + 1) );
  • Step 3 : Define function fun

void fun(int c)
{
        c = 99;
}
  • Step 4 : Note that it is call by Value for below reason

Condition 1 : Declaration has TWO dereference operators [ ] and [ ]

Condition 2 : Expression has TWO dereference operators * and *

Condition 3 : Expression DOES NOT have & operator

Means changing value of integer inside function DOES NOT affect value of integer in Caller !

  • See full program below

#include <stdio.h>

void fun(int c)
{
        c = 99;
}

int main(void)
{
        int a[3][4] = {
                {1, 2, 3, 4},
                {10, 20, 30, 40},
                {100, 200, 300, 400}
        };

        printf("----- Before call by value -----\n");
        printf("**a = %d\n", **a);
        printf("*(*(a + 1) + 0)  = %d\n", *(*(a + 1) + 0) );
        printf("*(*(a + 1) + 1)  = %d\n", *(*(a + 1) + 1) );

        fun( **a );

        fun( *(*(a + 1) + 0) );

        fun( *(*(a + 1) + 1) );

        printf("----- After call by value -----\n");
        printf("**a = %d\n", **a);
        printf("*(*(a + 1) + 0)  = %d\n", *(*(a + 1) + 0) );
        printf("*(*(a + 1) + 1)  = %d\n", *(*(a + 1) + 1) );

        return 0;
}
  • Output is as below

----- Before call by value -----
**a = 1
*(*(a + 1) + 0)  = 10
*(*(a + 1) + 1)  = 20

----- After call by value -----
**a = 1
*(*(a + 1) + 0)  = 10
*(*(a + 1) + 1)  = 20

Let us look at examples of Call by Reference

  • Step 1 : Consider a two dimensional array

int a[3][4] = {
        {1, 2, 3, 4},
        {10, 20, 30, 40},
        {100, 200, 300, 400}
};

There are 3 single dimension arrays in int a[3][4]

  • a[0]

  • a[1]

  • a[2]

a[0] is also equal to *a

a[1] is also equal to *(a + 1)

a[2] is also equal to *(a + 2)

a[0] is also equal to &a[0][0]

a[1] is also equal to &a[1][0]

a[2] is also equal to &a[2][0]

  • Step 2.1 : Method 1 : Pass &a[0][0], &a[1][0], &a[2][0] to a function fun

fun( &a[0][0] );

fun( &a[1][0] );

fun( &a[2][0] );
  • Step 2.2 : Method 2 : Pass a[0], a[1], a[2] to a function fun

fun( a[0] );

fun( a[1] );

fun( a[2] );
  • Step 2.3 : Method 3 : Pass *a, *(a + 1), *(a + 2) to a function fun

fun( *a );

fun( *(a + 1) );

fun( *(a + 2) );
  • Step 3.1 : Define function fun

void fun(int *ptr)
{
}
  • Step 4 : Note that it is call by Reference. Means contents of single dimension array can be changed inside function fun

void fun(int *ptr)
{
        for (int i = 0; i < 4; i++)
        {
                printf("ptr[%d] = %d\n", i, ptr[i] );
        }
}
  • See full program below

#include <stdio.h>

void fun(int *ptr)
{
        for (int i = 0; i < 4; i++)
        {
                printf("ptr[%d] = %d\n", i, ptr[i] );
        }
}

int main(void)
{
        int a[3][4] = {
                {1, 2, 3, 4},
                {10, 20, 30, 40},
                {100, 200, 300, 400}
        };

        printf("Method 1 : Access Single dimension arrays\n");

        fun( &a[0][0] );

        fun( &a[1][0] );

        fun( &a[2][0] );

        printf("Method 2 : Access Single dimension arrays\n");

        fun( a[0] );

        fun( a[1] );

        fun( a[2] );

        printf("Method 3 : Access Single dimension arrays\n");

        fun( *a );

        fun( *(a + 1) );

        fun( *(a + 2) );

        return 0;
}
  • Output is as below

Method 1 : Access Single dimension arrays
ptr[0] = 1
ptr[1] = 2
ptr[2] = 3
ptr[3] = 4
ptr[0] = 10
ptr[1] = 20
ptr[2] = 30
ptr[3] = 40
ptr[0] = 100
ptr[1] = 200
ptr[2] = 300
ptr[3] = 400

Method 2 : Access Single dimension arrays
ptr[0] = 1
ptr[1] = 2
ptr[2] = 3
ptr[3] = 4
ptr[0] = 10
ptr[1] = 20
ptr[2] = 30
ptr[3] = 40
ptr[0] = 100
ptr[1] = 200
ptr[2] = 300
ptr[3] = 400

Method 3 : Access Single dimension arrays
ptr[0] = 1
ptr[1] = 2
ptr[2] = 3
ptr[3] = 4
ptr[0] = 10
ptr[1] = 20
ptr[2] = 30
ptr[3] = 40
ptr[0] = 100
ptr[1] = 200
ptr[2] = 300
ptr[3] = 400
  • Step 1 : Consider a two dimensional array

int a[3][4] = {
        {1, 2, 3, 4},
        {10, 20, 30, 40},
        {100, 200, 300, 400}
};

There are 3 single dimension arrays in int a[3][4]

  • a[0]

  • a[1]

  • a[2]

Address of single dimension arrays is simply

  • &a[0]

  • &a[1]

  • &a[2]

  • &a[0] is also equal to a

  • &a[1] is also equal to a + 1

  • &a[2] is also equal to a + 2

  • Step 2.1 : Method 1 : Pass address of single dimension arrays to a function fun

fun( &a[0] );

fun( &a[1] );

fun( &a[2] );
  • Step 2.2 : Method 2 : Pass address of single dimension arrays to a function fun

fun( a );

fun( a + 1 );

fun( a + 2 );
  • Step 3.1 : Define the function fun

void fun(int (*ptr)[4] )
{
}
  • Step 3.2 : Define the function fun to change the contents of single dimension array integer by integer

void fun(int (*ptr)[4] )
{
        (*ptr)[0] = 11;
        (*ptr)[1] = 22;
        (*ptr)[2] = 33;
        (*ptr)[3] = 44;
}
  • See full program below

#include <stdio.h>

void fun(int (*ptr)[4] )
{
        (*ptr)[0] = 11;
        (*ptr)[1] = 22;
        (*ptr)[2] = 33;
        (*ptr)[3] = 44;
}

int main(void)
{
        int a[3][4] = {
                {1, 2, 3, 4},
                {10, 20, 30, 40},
                {100, 200, 300, 400}
        };

        printf("----- Before call by referene -----\n");

        for (int i = 0; i < 3; i++)
        {
                for (int j = 0; j < 4; j++)
                {
                        printf("a[%d][%d] = %d\n", i, j, a[i][j]);
                }
        }

        //Method 1 : Access Single dimension arrays. Call by reference

        fun( &a[0] );

        fun( &a[1] );

        fun( &a[2] );

        //Method 2 : Access Single dimension arrays. Call by reference

        fun( a );

        fun( a + 1 );

        fun( a + 2 );

        printf("----- After call by referene -----\n");

        for (int i = 0; i < 3; i++)
        {
                for (int j = 0; j < 4; j++)
                {
                        printf("a[%d][%d] = %d\n", i, j, a[i][j]);
                }
        }

        return 0;
}
  • Output is as below

----- Before call by referene -----
a[0][0] = 1
a[0][1] = 2
a[0][2] = 3
a[0][3] = 4
a[1][0] = 10
a[1][1] = 20
a[1][2] = 30
a[1][3] = 40
a[2][0] = 100
a[2][1] = 200
a[2][2] = 300
a[2][3] = 400

----- After call by referene -----
a[0][0] = 11
a[0][1] = 22
a[0][2] = 33
a[0][3] = 44
a[1][0] = 11
a[1][1] = 22
a[1][2] = 33
a[1][3] = 44
a[2][0] = 11
a[2][1] = 22
a[2][2] = 33
a[2][3] = 44
  • Step 1 : Consider a two dimensional array

int a[3][4] = {
        {1, 2, 3, 4},
        {10, 20, 30, 40},
        {100, 200, 300, 400}
};
  • Step 2 : Pass Address of Double Dimension array to a function

fun(&a);
  • Step 3.1 : Define function fun

void fun(int (*ptr)[3][4] )
{

}
  • Step 3.2 : Access and change individual integers inside function fun

int data = 100;

for (int i = 0 ; i < 3; i++) {
        for (int j = 0 ; j < 4; j++) {
                (*ptr)[i][j] = ++data;
        }
}
  • See full program below

#include <stdio.h>

void fun(int (*ptr)[3][4] )
{
        // Change Individual integers
        int data = 100;

        for (int i = 0 ; i < 3; i++) {
                for (int j = 0 ; j < 4; j++) {
                        (*ptr)[i][j] = ++data;
                }
        }
}

int main(void)
{
        int a[3][4] = {
                {1, 2, 3, 4},
                {10, 20, 30, 40},
                {100, 200, 300, 400}
        };

        printf("----- Before call by reference -----\n");

        for (int i = 0 ; i < 3; i++) {
                for (int j = 0 ; j < 4; j++) {
                        printf("a[%d][%d] = %d\n", i, j, a[i][j]);
                }
        }

        fun(&a);

        printf("----- After call by reference -----\n");

        for (int i = 0 ; i < 3; i++) {
                for (int j = 0 ; j < 4; j++) {
                        printf("a[%d][%d] = %d\n", i, j, a[i][j]);
                }
        }

        return 0;
}
  • Output is as below

----- Before call by reference -----
a[0][0] = 1
a[0][1] = 2
a[0][2] = 3
a[0][3] = 4
a[1][0] = 10
a[1][1] = 20
a[1][2] = 30
a[1][3] = 40
a[2][0] = 100
a[2][1] = 200
a[2][2] = 300
a[2][3] = 400

----- After call by reference -----
a[0][0] = 101
a[0][1] = 102
a[0][2] = 103
a[0][3] = 104
a[1][0] = 105
a[1][1] = 106
a[1][2] = 107
a[1][3] = 108
a[2][0] = 109
a[2][1] = 110
a[2][2] = 111
a[2][3] = 112