Functions and Structure Single Dimension Array

In this section, you are going to learn

What are the calling conventions of structure single dimension array ?

Call by Value

Call by Reference

struct ABC {
        type1 member1;
        type2 member2;
        type3 member3;
};

struct ABC array_name[Column];

Consider a Structure Single Dimension Array

struct ABC {
        int a;
        int b;
        int c;
};

struct ABC x[5];

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(x[0])

void fun(struct ABC x) { }

  • Call by Value

fun(x[1])

void fun(struct ABC x) { }

  • Call by Value

fun(x[4])

void fun(struct ABC x) { }

  • Call by Value

fun(&x[0])

void fun(struct ABC *p) { }

  • Call by Reference

fun(&x[1])

void fun(struct ABC *p) { }

  • Call by Reference

fun(&x[4])

void fun(struct ABC *p) { }

  • Call by Reference

fun(*x)

void fun(struct ABC x) { }

  • Call by Value

fun(*(x + 1))

void fun(struct ABC x) { }

  • Call by Value

fun(*(x + 4))

void fun(struct ABC x) { }

  • Call by Value

fun(x)

void fun(struct ABC *p) { }

  • Call by Reference

fun(x + 1)

void fun(struct ABC *p) { }

  • Call by Reference

fun(x + 4)

void fun(struct ABC *p) { }

  • Call by Reference

fun(&x)

void fun(struct ABC (*p) [4] ) { }

  • Call by Reference

If Declaration has ONE dereference operator, and

  • Expression has ONE dereference operator [], and

  • Expression does not have &

  • then it is call by value

If Declaration has ONE dereference operators, and

  • Expression has ONE dereference operator *, and

  • Expression does not have &

  • then it is call by value

If Declaration has ONE dereference operator, and

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

  • Expression has ONE &

  • then it is call by reference

  • Example : &x[0]

If Declaration has ONE dereference operator, and

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

  • Expression has ZERO & operator

  • then it is call by reference

  • Example : x + 1, x + 4

If Declaration has ONE dereference operator, and

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

  • Expression has ONE & operator

  • then it is call by reference

  • Example : &x

Let us look at examples of Call by Value

Example for Call By Value with [ ]

  • Step 1 : Define a structure array x

struct ABC {
        int a;
        int b;
        int c;
};

struct ABC x[5] = {
        {.a = 1, .b = 2, .c = 3},
        {.a = 4, .b = 5, .c = 6},
        {.a = 7, .b = 8, .c = 9},
        {.a = 10, .b = 11, .c = 12},
        {.a = 13, .b = 14, .c = 15},
};
  • Step 2 : Pass an individual structure x[2] to a function. Call by Value

fun(x[2]);

Individual array elements can be accessed using [ ]

In this case x[2] is third structure in the array

x[2] is fully dereferenced and there is no & symbol in fun(x[2]). Hence this is Call By Value

  • Step 3 : Define function fun

void fun(struct ABC x)
{

}
  • Step 4 : Change value of x inside function fun

void fun(struct ABC x)
{
        x.a = 100;
        x.b = 101;
        x.c = 102;
}
  • See the full program below

#include <stdio.h>

struct ABC {
        int a;
        int b;
        int c;
};

void fun(struct ABC x)
{
        x.a = 100;
        x.b = 101;
        x.c = 102;
}

int main(void)
{
        struct ABC x[5] = {
                {.a = 1, .b = 2, .c = 3},
                {.a = 4, .b = 5, .c = 6},
                {.a = 7, .b = 8, .c = 9},
                {.a = 10, .b = 11, .c = 12},
                {.a = 13, .b = 14, .c = 15},
        };

        printf("----- Before Call By Value -----\n");
        printf("x[2].a = %d\n", x[2].a);
        printf("x[2].b = %d\n", x[2].b);
        printf("x[2].c = %d\n", x[2].c);

        fun(x[2]);

        printf("----- After Call By Value -----\n");
        printf("x[2].a = %d\n", x[2].a);
        printf("x[2].b = %d\n", x[2].b);
        printf("x[2].c = %d\n", x[2].c);

        return 0;
}
  • Output is as below

----- Before Call By Value -----
x[2].a = 7
x[2].b = 8
x[2].c = 9

----- After Call By Value -----
x[2].a = 7
x[2].b = 8
x[2].c = 9

Changing value of x inside function fun DOES NOT change a[2] in array a

Example for Call By Value with *

  • Step 1 : Define a structure array x

struct ABC {
        int a;
        int b;
        int c;
};

struct ABC x[5] = {
        {.a = 1, .b = 2, .c = 3},
        {.a = 4, .b = 5, .c = 6},
        {.a = 7, .b = 8, .c = 9},
        {.a = 10, .b = 11, .c = 12},
        {.a = 13, .b = 14, .c = 15},
};
  • Step 2 : Pass an individual structure *(x + 2) to a function. Call by Value

fun( *(x + 2) );

Individual array elements can be accessed using *

In this case *(x + 2) is third structure in the array

*(x + 2) is fully dereferenced and there is no & symbol in fun( *(x + 2) ). Hence this is Call By Value

  • Step 3 : Define function fun

void fun(struct ABC x)
{

}
  • Step 4 : Change value of x inside function fun

void fun(struct ABC x)
{
        x.a = 100;
        x.b = 101;
        x.c = 102;
}
  • See the full program below

#include <stdio.h>

struct ABC {
        int a;
        int b;
        int c;
};

void fun(struct ABC x)
{
        x.a = 100;
        x.b = 101;
        x.c = 102;
}

int main(void)
{
        struct ABC x[5] = {
                {.a = 1, .b = 2, .c = 3},
                {.a = 4, .b = 5, .c = 6},
                {.a = 7, .b = 8, .c = 9},
                {.a = 10, .b = 11, .c = 12},
                {.a = 13, .b = 14, .c = 15},
        };

        printf("----- Before Call By Value -----\n");
        printf(" (*(x + 2)).a = %d\n", (*(x + 2)).a );
        printf(" (*(x + 2)).b = %d\n", (*(x + 2)).b );
        printf(" (*(x + 2)).c = %d\n", (*(x + 2)).c );

        fun( *(x + 2) );

        printf("----- After Call By Value -----\n");
        printf(" (*(x + 2)).a = %d\n", (*(x + 2)).a );
        printf(" (*(x + 2)).b = %d\n", (*(x + 2)).b );
        printf(" (*(x + 2)).c = %d\n", (*(x + 2)).c );

        return 0;
}
  • Output is as below

----- Before Call By Value -----
 (*(x + 2)).a = 7
 (*(x + 2)).b = 8
 (*(x + 2)).c = 9

----- After Call By Value -----
 (*(x + 2)).a = 7
 (*(x + 2)).b = 8
 (*(x + 2)).c = 9

Changing value of x inside function fun DOES NOT change *(x + 2) in array x

Remember x[2] and *(x + 2) are one and the same

Let us look at examples of Call by Reference

Example for Call By Reference with &x[ ]

  • Step 1 : Define a structure array x

struct ABC {
        int a;
        int b;
        int c;
};

struct ABC x[5] = {
        {.a = 1, .b = 2, .c = 3},
        {.a = 4, .b = 5, .c = 6},
        {.a = 7, .b = 8, .c = 9},
        {.a = 10, .b = 11, .c = 12},
        {.a = 13, .b = 14, .c = 15},
};
  • Step 2 : Pass address of an individual structure &x[2] to a function. Call by Reference

fun( &x[2] );

Address of individual array elements can be accessed using &

In this case &x[2] is the address of third structure in the array

Since we are passing address of third structure to function fun, it is called call by reference with respect to third structure

  • Step 3 : Define function fun

void fun(struct ABC *x)
{

}
  • Step 4 : Change value of *x inside function fun

void fun(struct ABC *x)
{
        x->a = 777;
        x->b = 888;
        x->c = 999;
}
  • See the full program below

#include <stdio.h>

struct ABC {
        int a;
        int b;
        int c;
};

void fun(struct ABC *x)
{
        x->a = 777;
        x->b = 888;
        x->c = 999;
}

int main(void)
{
        struct ABC x[5] = {
                {.a = 1, .b = 2, .c = 3},
                {.a = 4, .b = 5, .c = 6},
                {.a = 7, .b = 8, .c = 9},
                {.a = 10, .b = 11, .c = 12},
                {.a = 13, .b = 14, .c = 15},
        };

        printf("----- Before Call By Reference -----\n");
        printf("x[2].a = %d\n", x[2].a);
        printf("x[2].b = %d\n", x[2].b);
        printf("x[2].c = %d\n", x[2].c);

        fun( &x[2] );

        printf("----- After Call By Reference -----\n");
        printf("x[2].a = %d\n", x[2].a);
        printf("x[2].b = %d\n", x[2].b);
        printf("x[2].c = %d\n", x[2].c);

        return 0;
}
  • Output is as below

----- Before Call By Reference -----
x[2].a = 7
x[2].b = 8
x[2].c = 9

----- After Call By Reference -----
x[2].a = 777
x[2].b = 888
x[2].c = 999

Changing value of *x inside function fun CHANGES x[2] in array x

Example for Call By Reference with (x + n)

  • Step 1 : Define a structure array x

struct ABC {
        int a;
        int b;
        int c;
};

struct ABC x[5] = {
        {.a = 1, .b = 2, .c = 3},
        {.a = 4, .b = 5, .c = 6},
        {.a = 7, .b = 8, .c = 9},
        {.a = 10, .b = 11, .c = 12},
        {.a = 13, .b = 14, .c = 15},
};
  • Step 2 : Pass address of individual structure x + 2 to a function. Call by Reference

fun( x + 2 );

In this case x + 2 is the address of third structure in the array

Since we are passing address of third structure to function fun, it is called call by reference with respect to third structure

  • Step 3 : Define function fun

void fun(struct ABC *x)
{

}
  • Step 4 : Change value of *x inside function fun

void fun(struct ABC *x)
{
        x->a = 777;
        x->b = 888;
        x->c = 999;
}
  • See the full program below

#include <stdio.h>

struct ABC {
        int a;
        int b;
        int c;
};

void fun(struct ABC *x)
{
        x->a = 777;
        x->b = 888;
        x->c = 999;
}

int main(void)
{
        struct ABC x[5] = {
                {.a = 1, .b = 2, .c = 3},
                {.a = 4, .b = 5, .c = 6},
                {.a = 7, .b = 8, .c = 9},
                {.a = 10, .b = 11, .c = 12},
                {.a = 13, .b = 14, .c = 15},
        };

        printf("----- Before Call By Reference -----\n");
        printf("x[2].a = %d\n", x[2].a);
        printf("x[2].b = %d\n", x[2].b);
        printf("x[2].c = %d\n", x[2].c);

        fun( x + 2 );

        printf("----- After Call By Reference -----\n");
        printf("x[2].a = %d\n", x[2].a);
        printf("x[2].b = %d\n", x[2].b);
        printf("x[2].c = %d\n", x[2].c);

        return 0;
}
  • Output is as below

----- Before Call By Reference -----
x[2].a = 7
x[2].b = 8
x[2].c = 9

----- After Call By Reference -----
x[2].a = 777
x[2].b = 888
x[2].c = 999

Changing value of *x inside function fun CHANGES x[2] in array x

  • Step 1 : Consider a structure array

struct ABC {
        int a;
        int b;
        int c;
};

struct ABC x[5] = {
        {.a = 1, .b = 2, .c = 3},
        {.a = 4, .b = 5, .c = 6},
        {.a = 7, .b = 8, .c = 9},
        {.a = 10, .b = 11, .c = 12},
        {.a = 13, .b = 14, .c = 15},
};
  • Step 2 : Pass full array array to a function

fun( x );

Note that we are passing starting address of array

Hence function fun has read and write access to all Bytes of array

  • Step 3 : Define a function

void fun(struct ABC *x)
{
        for (int i = 0; i < 5; i++)
        {
                x[i].a = 777;
                x[i].b = 888;
                x[i].c = 999;
        }
}

function fun has access to all structures

  • See full program below

#include <stdio.h>

struct ABC {
        int a;
        int b;
        int c;
};

void fun(struct ABC *x)
{
        for (int i = 0; i < 5; i++)
        {
                x[i].a = 777;
                x[i].b = 888;
                x[i].c = 999;
        }
}

int main(void)
{
        struct ABC x[5] = {
                {.a = 1, .b = 2, .c = 3},
                {.a = 4, .b = 5, .c = 6},
                {.a = 7, .b = 8, .c = 9},
                {.a = 10, .b = 11, .c = 12},
                {.a = 13, .b = 14, .c = 15},
        };

        printf("----- Before Call By Reference -----\n");
        for (int i = 0; i < 5; i++)
        {
                printf("x[%d].a = %d ", i, x[i].a);
                printf("x[%d].b = %d ", i, x[i].b);
                printf("x[%d].c = %d ", i, x[i].c);
                printf("\n");
        }

        fun(x);

        printf("----- After Call By Reference -----\n");
        for (int i = 0; i < 5; i++)
        {
                printf("x[%d].a = %d ", i, x[i].a);
                printf("x[%d].b = %d ", i, x[i].b);
                printf("x[%d].c = %d ", i, x[i].c);
                printf("\n");
        }

        return 0;
}
  • Output is as below

----- Before Call By Reference -----
x[0].a = 1 x[0].b = 2 x[0].c = 3
x[1].a = 4 x[1].b = 5 x[1].c = 6
x[2].a = 7 x[2].b = 8 x[2].c = 9
x[3].a = 10 x[3].b = 11 x[3].c = 12
x[4].a = 13 x[4].b = 14 x[4].c = 15

----- After Call By Reference -----
x[0].a = 777 x[0].b = 888 x[0].c = 999
x[1].a = 777 x[1].b = 888 x[1].c = 999
x[2].a = 777 x[2].b = 888 x[2].c = 999
x[3].a = 777 x[3].b = 888 x[3].c = 999
x[4].a = 777 x[4].b = 888 x[4].c = 999
  • Step 1 : Consider a structure array

struct ABC {
        int a;
        int b;
        int c;
};

struct ABC x[5] = {
        {.a = 1, .b = 2, .c = 3},
        {.a = 4, .b = 5, .c = 6},
        {.a = 7, .b = 8, .c = 9},
        {.a = 10, .b = 11, .c = 12},
        {.a = 13, .b = 14, .c = 15},
};
  • Step 2 : Pass full array by reference

fun( a + 2 );

Note that we are passing part of the array by reference

In this case, we are passing address of 3rd structure

Hence function fun has read and write access to structures at indexes 2,3,4 in forward direction

Hence function fun has read and write access to structures at indexes 0, 1 in backward direction

  • Step 3 : Define a function

void fun(struct ABC *ptr)
{
        ptr[-2].a = 55; // Same as x[0]
        ptr[-1].a = 66; // Same as x[1]
        ptr[0].a  = 77; // Same as x[2]
        ptr[1].a  = 88; // Same as x[3]
        ptr[2].a  = 99; // Same as x[4]
}

Note the relative access mechanism used inside function fun

  • See full program below

#include <stdio.h>

struct ABC {
        int a;
        int b;
        int c;
};

void fun(struct ABC *ptr)
{
        ptr[-2].a = 55; // Same as x[0]
        ptr[-1].a = 66; // Same as x[1]
        ptr[0].a  = 77; // Same as x[2]
        ptr[1].a  = 88; // Same as x[3]
        ptr[2].a  = 99; // Same as x[4]
}

int main(void)
{
        struct ABC x[5] = {
                {.a = 1, .b = 2, .c = 3},
                {.a = 4, .b = 5, .c = 6},
                {.a = 7, .b = 8, .c = 9},
                {.a = 10, .b = 11, .c = 12},
                {.a = 13, .b = 14, .c = 15},
        };

        printf("----- Before Call By Reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("x[%d].a = %d ", i, x[i].a);
                printf("x[%d].b = %d ", i, x[i].b);
                printf("x[%d].c = %d ", i, x[i].c);
                printf("\n");
        }

        fun(x + 2);

        printf("----- After Call By Reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("x[%d].a = %d ", i, x[i].a);
                printf("x[%d].b = %d ", i, x[i].b);
                printf("x[%d].c = %d ", i, x[i].c);
                printf("\n");
        }

        return 0;
}
  • Output is as below

----- Before Call By Reference -----
x[0].a = 1 x[0].b = 2 x[0].c = 3
x[1].a = 4 x[1].b = 5 x[1].c = 6
x[2].a = 7 x[2].b = 8 x[2].c = 9
x[3].a = 10 x[3].b = 11 x[3].c = 12
x[4].a = 13 x[4].b = 14 x[4].c = 15

----- After Call By Reference -----
x[0].a = 55 x[0].b = 2 x[0].c = 3
x[1].a = 66 x[1].b = 5 x[1].c = 6
x[2].a = 77 x[2].b = 8 x[2].c = 9
x[3].a = 88 x[3].b = 11 x[3].c = 12
x[4].a = 99 x[4].b = 14 x[4].c = 15
  • Step 1 : Consider a structure array

struct ABC {
        int a;
        int b;
        int c;
};

struct ABC x[5] = {
        {.a = 1, .b = 2, .c = 3},
        {.a = 4, .b = 5, .c = 6},
        {.a = 7, .b = 8, .c = 9},
        {.a = 10, .b = 11, .c = 12},
        {.a = 13, .b = 14, .c = 15},
};
  • Step 2 : Pass the address of array a to function fun

fun(&a);
  • Step 3 : Define the function fun

void fun( struct ABC (*ptr)[5] )
{

}

Note that struct ABC (*ptr)[5] is pointer to an array of 5 structures

Which means incrementing ptr will increment by 5 Structures and decrementing ptr will decrement by 5 Structures

  • Step 4 : Access individual structures inside function fun

void fun( struct ABC (*ptr)[10] )
{
        //Change individual structures
        (*ptr)[0].a = 55;
        (*ptr)[1].a = 66;
        (*ptr)[2].a = 77;
        (*ptr)[3].a = 88;
        (*ptr)[4].a = 99;
}
  • See the full program below

#include <stdio.h>

struct ABC {
        int a;
        int b;
        int c;
};

void fun( struct ABC (*ptr)[5] )
{
        //Change individual structures
        (*ptr)[0].a = 55;
        (*ptr)[1].a = 66;
        (*ptr)[2].a = 77;
        (*ptr)[3].a = 88;
        (*ptr)[4].a = 99;
}

int main(void)
{
        struct ABC x[5] = {
                {.a = 1, .b = 2, .c = 3},
                {.a = 4, .b = 5, .c = 6},
                {.a = 7, .b = 8, .c = 9},
                {.a = 10, .b = 11, .c = 12},
                {.a = 13, .b = 14, .c = 15},
        };

        printf("----- Before Call By Reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("x[%d].a = %d ", i, x[i].a);
                printf("x[%d].b = %d ", i, x[i].b);
                printf("x[%d].c = %d ", i, x[i].c);
                printf("\n");
        }

        fun(&x);

        printf("----- After Call By Reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("x[%d].a = %d ", i, x[i].a);
                printf("x[%d].b = %d ", i, x[i].b);
                printf("x[%d].c = %d ", i, x[i].c);
                printf("\n");
        }

        return 0;
}
  • Output is as below

----- Before Call By Reference -----
x[0].a = 1 x[0].b = 2 x[0].c = 3
x[1].a = 4 x[1].b = 5 x[1].c = 6
x[2].a = 7 x[2].b = 8 x[2].c = 9
x[3].a = 10 x[3].b = 11 x[3].c = 12
x[4].a = 13 x[4].b = 14 x[4].c = 15

----- After Call By Reference -----
x[0].a = 55 x[0].b = 2 x[0].c = 3
x[1].a = 66 x[1].b = 5 x[1].c = 6
x[2].a = 77 x[2].b = 8 x[2].c = 9
x[3].a = 88 x[3].b = 11 x[3].c = 12
x[4].a = 99 x[4].b = 14 x[4].c = 15