Functions and Structure Double Dimension Array
In this section, you are going to learn
What are the calling conventions of structure double dimension array ?
Call by Value
Call by Reference
Revisit Basics : Basics of Structure Double Dimension Array
Topics in this section,
struct ABC {
type1 member1;
type2 member2;
type3 member3;
etc.,
};
struct ABC array_name[Row][Column];
Consider a structure double dimension array
struct ABC {
int a;
int b;
int c;
};
struct ABC x[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(x[0][0]) |
void fun(struct ABC x) {} |
|
fun(x[1][0]) |
void fun(struct ABC x) {} |
|
fun(x[2][0]) |
void fun(struct ABC x) {} |
|
fun(&x[0][0]) |
void fun(struct ABC *p) { } |
|
fun(&x[1][0]) |
void fun(struct ABC *p) { } |
|
fun(&x[2][0]) |
void fun(struct ABC *p) { } |
|
fun(**x) |
void fun(struct ABC x) {} |
|
fun(*(*(x + 1) + 0)) |
void fun(struct ABC x) {} |
|
fun(*(*(x + 2) + 0)) |
void fun(struct ABC x) {} |
|
fun(x[0]) |
void fun(struct ABC *p) { } |
|
fun(x[1]) |
void fun(struct ABC *p) { } |
|
fun(x[2]) |
void fun(struct ABC *p) { } |
|
fun(&x[0]) |
void fun(struct ABC (*p)[4]) { } |
|
fun(&x[1]) |
void fun(struct ABC (*p)[4]) { } |
|
fun(&x[2]) |
void fun(struct ABC (*p)[4]) { } |
|
fun(*x) |
void fun(struct ABC *p) { } |
|
fun(*(x + 1)) |
void fun(struct ABC *p) { } |
|
fun(*(x + 2)) |
void fun(struct ABC *p) { } |
|
fun(x) |
void fun(struct ABC (*p)[4]) { } |
|
fun(x + 1) |
void fun(struct ABC (*p)[4]) { } |
|
fun(x + 2) |
void fun(struct ABC (*p)[4]) { } |
|
fun(&x) |
void fun(struct ABC (*p)[3][4]) { } |
|
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
struct ABC {
int a;
int b;
int c;
};
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
Condition 1 : Declaration has TWO dereference operators [ ] and [ ]
Step 2 : Consider an expression
x[1][1]
Condition 2 : Expression has TWO dereference operators [ ] and [ ]
Note : [ ]
and *
are dereference operators
Condition 3 : Expression DOES NOT have &
operator
Hence x[1][1]
is Call By Value
Step 1 : Consider an array
struct ABC {
int a;
int b;
int c;
};
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
Condition 1 : Declaration has TWO dereference operators [ ] and [ ]
Step 2 : Consider an expression
**x
Condition 2 : Expression has TWO dereference operators * and *
Note : [ ]
and *
are dereference operators
Condition 3 : Expression DOES NOT have &
operator
Hence **x
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 : &x[0][0]
If Declaration has two dereference operators, and
Expression has one dereference operator [ ] or *, and
then it is call by reference
Example : &x[0], x[0], *x
If Declaration has two dereference operators, and
Expression has zero dereference operators, and
then it is call by reference
Example : x, &x, x + 1, x + 2
Step 1 : Consider an array
struct ABC {
int a;
int b;
int c;
};
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
Condition 1 : Declaration has TWO dereference operators [ ] and [ ]
Step 2 : Consider an expression
&x[1][1]
Condition 2 : Expression has TWO dereference operators * and *
Note : [ ]
and *
are dereference operators
Condition 3 : Expression has &
operator
Hence &x[1][1]
is Call By Reference
Step 1 : Consider an array
struct ABC {
int a;
int b;
int c;
};
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
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 x[1]
is Call By Reference
Let us look at examples of Call by Value
Step 1 : Consider a two dimensional array
struct ABC {
int a;
int b;
int c;
};
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
Step 2 : Pass x[0][0], x[1][0], x[1][1] to a function
fun
fun(x[0][0]);
fun(x[1][0]);
fun(x[1][1]);
Step 3 : Define function
fun
void fun(struct ABC y)
{
y.a = 99;
y.b = 100;
y.x = 101;
}
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 structure inside function DOES NOT affect value of structure in Caller !
See full program below
#include <stdio.h>
struct ABC {
int a;
int b;
int c;
};
void fun(struct ABC y)
{
y.a = 99;
y.b = 100;
y.c = 101;
}
int main(void)
{
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
printf("----- Before Call By Value -----\n");
printf("x[0][0].a = %d\n", x[0][0].a);
printf("x[1][0].a = %d\n", x[1][0].a);
printf("x[1][1].a = %d\n", x[1][1].a);
fun(x[0][0]);
fun(x[1][0]);
fun(x[1][1]);
printf("----- After Call By Value -----\n");
printf("x[0][0].a = %d\n", x[0][0].a);
printf("x[1][0].a = %d\n", x[1][0].a);
printf("x[1][1].a = %d\n", x[1][1].a);
return 0;
}
Output is as below
----- Before Call By Value -----
x[0][0].a = 1
x[1][0].a = 10
x[1][1].a = 13
----- After Call By Value -----
x[0][0].a = 1
x[1][0].a = 10
x[1][1].a = 13
Step 1 : Consider a two dimensional array
struct ABC {
int a;
int b;
int c;
};
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
Step 2 : Pass **x, *(*(x + 1) + 0), *(*(x + 1) + 1) to a function
fun
fun( **x );
fun( *(*(x + 1) + 0) );
fun( *(*(x + 1) + 1) );
Step 3 : Define function
fun
void fun(struct ABC y)
{
y.a = 99;
y.b = 100;
y.c = 101;
}
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 structure inside function DOES NOT affect value of structure in Caller !
See full program below
#include <stdio.h>
struct ABC {
int a;
int b;
int c;
};
void fun(struct ABC y)
{
y.a = 99;
y.b = 100;
y.c = 101;
}
int main(void)
{
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
printf("----- Before Call By Value -----\n");
printf(" (**x).a = %d\n", (**x).a);
printf(" (*(*(x + 1) + 0)).a = %d\n", (*(*(x + 1) + 0)).a );
printf(" (*(*(x + 1) + 1)).a = %d\n", (*(*(x + 1) + 1)).a );
fun( **x );
fun( *(*(x + 1) + 0) );
fun( *(*(x + 1) + 1) );
printf("----- After Call By Value -----\n");
printf(" (**x).a = %d\n", (**x).a);
printf(" (*(*(x + 1) + 0)).a = %d\n", (*(*(x + 1) + 0)).a );
printf(" (*(*(x + 1) + 1)).a = %d\n", (*(*(x + 1) + 1)).a );
return 0;
}
Output is as below
----- Before Call By Value -----
(**x).a = 1
(*(*(x + 1) + 0)).a = 10
(*(*(x + 1) + 1)).a = 13
----- After Call By Value -----
(**x).a = 1
(*(*(x + 1) + 0)).a = 10
(*(*(x + 1) + 1)).a = 13
Let us look at examples of Call by Reference
Step 1 : Consider a two dimensional array
struct ABC {
int a;
int b;
int c;
};
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
There are 2 single dimension arrays in struct ABC x[2][3]
x[0]
x[1]
x[0] is also equal to *x
x[1] is also equal to *(x + 1)
x[0] is also equal to &x[0][0]
x[1] is also equal to &x[1][0]
Step 2.1 : Method 1 : Pass &x[0][0], &x[1][0] to a function
fun
fun( &x[0][0] );
fun( &x[1][0] );
Step 2.2 : Method 2 : Pass x[0], x[1], x[2] to a function
fun
fun( x[0] );
fun( x[1] );
Step 2.3 : Method 3 : Pass *a, *(a + 1) to a function
fun
fun( *x );
fun( *(x + 1) );
Step 3.1 : Define function
fun
void fun(struct ABC *ptr)
{
}
Step 4 : Note that it is call by Reference. Means contents of single dimension array can be changed inside function
fun
void fun(struct ABC *ptr)
{
for (int i = 0; i < 4; i++)
{
ptr[i].a = 99;
ptr[i].b = 100;
ptr[i].c = 101;
}
}
See full program below
#include <stdio.h>
struct ABC {
int a;
int b;
int c;
};
void fun(struct ABC *ptr)
{
for (int i = 0; i < 3; i++)
{
ptr[i].a = 99;
ptr[i].b = 100;
ptr[i].c = 101;
}
}
int main(void)
{
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
printf("----- Before Call By Reference -----\n");
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("x[%d][%d].a = %d\n", i, j, x[i][j].a);
printf("x[%d][%d].b = %d\n", i, j, x[i][j].b);
printf("x[%d][%d].c = %d\n", i, j, x[i][j].c);
}
}
// Method 1 : Access Single dimension arrays
fun( &x[0][0] );
fun( &x[1][0] );
// Method 2 : Access Single dimension arrays
fun( x[0] );
fun( x[1] );
// Method 3 : Access Single dimension arrays
fun( *x );
fun( *(x + 1) );
printf("----- After Call By Reference -----\n");
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("x[%d][%d].a = %d\n", i, j, x[i][j].a);
printf("x[%d][%d].b = %d\n", i, j, x[i][j].b);
printf("x[%d][%d].c = %d\n", i, j, x[i][j].c);
}
}
return 0;
}
Output is as below
----- Before Call By Reference -----
x[0][0].a = 1
x[0][0].b = 2
x[0][0].c = 3
x[0][1].a = 4
x[0][1].b = 5
x[0][1].c = 6
x[0][2].a = 7
x[0][2].b = 8
x[0][2].c = 9
x[1][0].a = 10
x[1][0].b = 11
x[1][0].c = 12
x[1][1].a = 13
x[1][1].b = 14
x[1][1].c = 15
x[1][2].a = 16
x[1][2].b = 17
x[1][2].c = 18
----- After Call By Reference -----
x[0][0].a = 99
x[0][0].b = 100
x[0][0].c = 101
x[0][1].a = 99
x[0][1].b = 100
x[0][1].c = 101
x[0][2].a = 99
x[0][2].b = 100
x[0][2].c = 101
x[1][0].a = 99
x[1][0].b = 100
x[1][0].c = 101
x[1][1].a = 99
x[1][1].b = 100
x[1][1].c = 101
x[1][2].a = 99
x[1][2].b = 100
x[1][2].c = 101
Step 1 : Consider a two dimensional array
struct ABC {
int a;
int b;
int c;
};
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
There are 2 single dimension arrays in struct ABC x[2][3]
x[0]
x[1]
Address of single dimension arrays is simply
&x[0]
&x[1]
&x[0] is also equal to a
&x[1] is also equal to a + 1
Step 2.1 : Method 1 : Pass address of single dimension arrays to a function
fun
fun( &x[0] );
fun( &x[1] );
Step 2.2 : Method 2 : Pass address of single dimension arrays to a function
fun
fun( a );
fun( a + 1 );
Step 3.1 : Define the function
fun
void fun(struct ABC (*ptr)[3] )
{
}
Step 3.2 : Define the function
fun
to change the contents of single dimension array structure by structure
void fun(struct ABC (*ptr)[3] )
{
(*ptr)[0].a = 777;
(*ptr)[1].a = 888;
(*ptr)[2].a = 999;
}
See full program below
#include <stdio.h>
struct ABC {
int a;
int b;
int c;
};
void fun(struct ABC (*ptr)[3] )
{
(*ptr)[0].a = 777;
(*ptr)[1].a = 888;
(*ptr)[2].a = 999;
}
int main(void)
{
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
printf("----- Before Call By Reference -----\n");
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("x[%d][%d].a = %d\n", i, j, x[i][j].a);
printf("x[%d][%d].b = %d\n", i, j, x[i][j].b);
printf("x[%d][%d].c = %d\n", i, j, x[i][j].c);
}
}
// Method 1 : Access Single dimension arrays
fun( &x[0] );
fun( &x[1] );
// Method 2 : Access Single dimension arrays
fun( x );
fun( x + 1 );
printf("----- After Call By Reference -----\n");
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("x[%d][%d].a = %d\n", i, j, x[i][j].a);
printf("x[%d][%d].b = %d\n", i, j, x[i][j].b);
printf("x[%d][%d].c = %d\n", i, j, x[i][j].c);
}
}
return 0;
}
Output is as below
----- Before Call By Reference -----
x[0][0].a = 1
x[0][0].b = 2
x[0][0].c = 3
x[0][1].a = 4
x[0][1].b = 5
x[0][1].c = 6
x[0][2].a = 7
x[0][2].b = 8
x[0][2].c = 9
x[1][0].a = 10
x[1][0].b = 11
x[1][0].c = 12
x[1][1].a = 13
x[1][1].b = 14
x[1][1].c = 15
x[1][2].a = 16
x[1][2].b = 17
x[1][2].c = 18
----- After Call By Reference -----
x[0][0].a = 777
x[0][0].b = 2
x[0][0].c = 3
x[0][1].a = 888
x[0][1].b = 5
x[0][1].c = 6
x[0][2].a = 999
x[0][2].b = 8
x[0][2].c = 9
x[1][0].a = 777
x[1][0].b = 11
x[1][0].c = 12
x[1][1].a = 888
x[1][1].b = 14
x[1][1].c = 15
x[1][2].a = 999
x[1][2].b = 17
x[1][2].c = 18
Step 1 : Consider a two dimensional array
struct ABC {
int a;
int b;
int c;
};
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
Step 2 : Pass Address of Double Dimension array to a function
fun(&x);
Step 3.1 : Define function
fun
void fun(struct ABC (*ptr)[2][3] )
{
}
Step 3.2 : Access and change individual structures inside function
fun
void fun(struct ABC (*ptr)[2][3] )
{
for (int i = 0 ; i < 2; i++) {
for (int j = 0 ; j < 3; j++) {
(*ptr)[i][j].a = 777;
(*ptr)[i][j].b = 888;
(*ptr)[i][j].c = 999;
}
}
}
See full program below
#include <stdio.h>
struct ABC {
int a;
int b;
int c;
};
void fun(struct ABC (*ptr)[2][3] )
{
for (int i = 0 ; i < 2; i++) {
for (int j = 0 ; j < 3; j++) {
(*ptr)[i][j].a = 777;
(*ptr)[i][j].b = 888;
(*ptr)[i][j].c = 999;
}
}
}
int main(void)
{
struct ABC x[2][3] = {
{
{.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},
{.a = 16, .b = 17, .c = 18},
},
};
printf("----- Before Call By Reference -----\n");
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("x[%d][%d].a = %d\n", i, j, x[i][j].a);
printf("x[%d][%d].b = %d\n", i, j, x[i][j].b);
printf("x[%d][%d].c = %d\n", i, j, x[i][j].c);
}
}
fun(&x);
printf("----- After Call By Reference -----\n");
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("x[%d][%d].a = %d\n", i, j, x[i][j].a);
printf("x[%d][%d].b = %d\n", i, j, x[i][j].b);
printf("x[%d][%d].c = %d\n", i, j, x[i][j].c);
}
}
return 0;
}
Output is as below
----- Before Call By Reference -----
x[0][0].a = 1
x[0][0].b = 2
x[0][0].c = 3
x[0][1].a = 4
x[0][1].b = 5
x[0][1].c = 6
x[0][2].a = 7
x[0][2].b = 8
x[0][2].c = 9
x[1][0].a = 10
x[1][0].b = 11
x[1][0].c = 12
x[1][1].a = 13
x[1][1].b = 14
x[1][1].c = 15
x[1][2].a = 16
x[1][2].b = 17
x[1][2].c = 18
----- After Call By Reference -----
x[0][0].a = 777
x[0][0].b = 888
x[0][0].c = 999
x[0][1].a = 777
x[0][1].b = 888
x[0][1].c = 999
x[0][2].a = 777
x[0][2].b = 888
x[0][2].c = 999
x[1][0].a = 777
x[1][0].b = 888
x[1][0].c = 999
x[1][1].a = 777
x[1][1].b = 888
x[1][1].c = 999
x[1][2].a = 777
x[1][2].b = 888
x[1][2].c = 999
Other topics of structure and functions
Current Module
Previous Module
Next Module
Other Modules