Pointer to a Single Dimension Array of Structures ================================================== In this section, you are going to learn .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow How to define and use Pointer to Single Dimension Arrays ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Pointer to an Array * :ref:`Syntax of Pointer to an array ` * :ref:`Pointer to an array increments by size of the array ` * :ref:`Pointer to an array : Passed as function arguement : Call by Value ` * :ref:`Pointer to an array : Passed as function arguement : Call by Reference ` * :ref:`Method 1 : Pointer to an array : How to print contents of single dimension array ? ` * :ref:`Method 2 : Pointer to an array : How to print contents of single dimension array ? ` * :ref:`Pointer to an array : Pointing to Single dimension array inside a Double dimension array ` * :ref:`Pointer to an array : Pointing to a block of memory in heap ` .. _ptr_to_array_struct_sp_ex_1: .. tab-set:: .. tab-item:: Syntax of Pointer to an array .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow type ( \*ptr ) [ size_of_array ]; An example is as below .. code-block:: c struct ABC a[3] = { {.a = 1, .b = 2}, {.a = 3, .b = 4}, {.a = 5, .b = 6} }; struct ABC (*ptr)[3]; ptr = &a; .. _ptr_to_array_struct_sp_ex_2: .. tab-set:: .. tab-item:: Pointer to an array increments by size of the array .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Pointer to an Array when incremented, increments by size of the array to which it is pointing to ! .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Pointer to an Array when decremented, decrements by size of the array to which it is pointing to ! .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Let us see how it is done. See below * Step 1 : Define a single dimension array .. code-block:: c struct ABC { int a; int b; }; struct ABC a[3] = { {.a = 1, .b = 2}, {.a = 3, .b = 4}, {.a = 5, .b = 6} }; * Step 2 : Define a pointer to an array .. code-block:: c struct ABC (*ptr)[3]; * Step 3 : Let pointer to an array, point to single dimension array .. code-block:: c ptr = &a; * Step 4 : Check pointer arithmetic .. code-block:: c printf("Before Increment : ptr = %lx\n", (unsigned long int) ptr); ptr++; printf("After Increment : ptr = %lx\n", (unsigned long int) ptr); * See full program below .. code-block:: c #include struct ABC { int a; int b; }; int main(void) { struct ABC a[3] = { {.a = 1, .b = 2}, {.a = 3, .b = 4}, {.a = 5, .b = 6} }; struct ABC (*ptr)[3]; ptr = &a; printf("Before Increment : ptr = %lx\n", (unsigned long int) ptr); ptr++; printf("After Increment : ptr = %lx\n", (unsigned long int) ptr); return 0; } * Output is as below .. code-block:: c Before Increment : ptr = 7ffda2b55830 After Increment : ptr = 7ffda2b55848 .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Observe that difference is 24 ! * ``sizeof(a)`` is 24 Bytes * ``ptr`` is pointer to an array of 3 structure objects with size of 24 Bytes .. _ptr_to_array_struct_sp_ex_3: .. tab-set:: .. tab-item:: Pointer to an array : Passed as function arguement : Call by Value .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow When Pointer to an Array is passed as argument, Prototype of function should match the type properly ! .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Let us see how it is done. See below * Step 1 : Define a single dimension array .. code-block:: c struct ABC { int a; int b; }; struct ABC a[3] = { {.a = 1, .b = 2}, {.a = 3, .b = 4}, {.a = 5, .b = 6} }; * Step 2 : Define a pointer to an array .. code-block:: c struct ABC (*ptr)[3]; * Step 3 : Let pointer to an array, point to single dimension array .. code-block:: c ptr = &a; * Step 4 : Pass ``ptr`` as argument to function ``fun`` .. code-block:: c fun(ptr); * Step 5 : Define function ``fun`` .. code-block:: c void fun( struct ABC (*p)[3] ) { } * See full program below .. code-block:: c #include struct ABC { int a; int b; }; void fun( struct ABC (*p)[3] ) { } int main(void) { struct ABC a[3] = { {.a = 1, .b = 2}, {.a = 3, .b = 4}, {.a = 5, .b = 6} }; struct ABC (*ptr)[3]; ptr = &a; fun(ptr); return 0; } .. _ptr_to_array_struct_sp_ex_8: .. tab-set:: .. tab-item:: Pointer to an array : Passed as function arguement : Call by Reference .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow When Pointer to an Array is passed as argument by call by reference, Prototype of function should match the type properly ! .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Let us see how it is done. See below * Step 1 : Define a Double dimension array .. code-block:: c struct ABC a[2][3] = { { {.a = 1, .b = 2}, {.a = 3, .b = 4}, {.a = 5, .b = 6} }, { {.a = 100, .b = 200}, {.a = 300, .b = 400}, {.a = 500, .b = 600} }, }; * Step 2 : Define a pointer to an array .. code-block:: c struct ABC (*ptr)[3]; * Step 3 : Let pointer to an array, point to single dimension array .. code-block:: c ptr = &a[0]; * Step 4 : Pass ``ptr`` as argument to function ``fun``. Call by reference .. code-block:: c fun(&ptr); * Step 5 : Define function ``fun`` .. code-block:: c void fun(struct ABC (**p)[3]) { for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { printf("(*p)[%d][%d].a = %d ", i, j, (*p)[i][j].a); printf("(*p)[%d][%d].b = %d ", i, j, (*p)[i][j].b); printf("\n"); } printf("\n"); } } .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow This is easy to understand ! Let us derive the rules * Rule 1 : Base rule in ``main`` .. code-block:: c ptr = &a[0]; * Rule 2 : Base rule in ``fun`` .. code-block:: c p = &ptr * Rule 2 : Move & from RHS to LHS. This becomes * on LHS .. code-block:: c *p = ptr * Rule 3 : Replace ``ptr`` referring to Rule 1 .. code-block:: c *p = &a[0] * Rule 4 : Move & from RHS to LHS. This becomes * on LHS .. code-block:: c **p = a[0] * Rule 5 : ``*`` and ``[ ]`` can be used interchangeably .. code-block:: c (*p)[0] = a[0] * Rule 6 : ``*`` and ``[ ]`` can be used interchangeably .. code-block:: c p[0][0] = a[0] * Rule 7 : ``*`` and ``[ ]`` can be used interchangeably .. code-block:: c p[0][0] = &a[0][0] * Rule 8 : Move & from RHS to LHS. This becomes * on LHS .. code-block:: c (*p)[0][0] = a[0][0] * Rule 9 : Extending Rule 8 .. code-block:: c (*p)[i][j] = a[i][j] * See full program below .. code-block:: c #include struct ABC { int a; int b; }; void fun(struct ABC (**p)[3]) { for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { printf("(*p)[%d][%d].a = %d ", i, j, (*p)[i][j].a); printf("(*p)[%d][%d].b = %d ", i, j, (*p)[i][j].b); printf("\n"); } printf("\n"); } } int main(void) { struct ABC a[2][3] = { { {.a = 1, .b = 2}, {.a = 3, .b = 4}, {.a = 5, .b = 6} }, { {.a = 100, .b = 200}, {.a = 300, .b = 400}, {.a = 500, .b = 600} }, }; struct ABC (*ptr)[3]; ptr = &a[0]; fun(&ptr); return 0; } * Output is as below .. code-block:: c (*p)[0][0].a = 1 (*p)[0][0].b = 2 (*p)[0][1].a = 3 (*p)[0][1].b = 4 (*p)[0][2].a = 5 (*p)[0][2].b = 6 (*p)[1][0].a = 100 (*p)[1][0].b = 200 (*p)[1][1].a = 300 (*p)[1][1].b = 400 (*p)[1][2].a = 500 (*p)[1][2].b = 600 .. _ptr_to_array_struct_sp_ex_4: .. tab-set:: .. tab-item:: Method 1 : Pointer to an array : How to print contents of single dimension array ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow We can use pointer to an array directly inorder to print the contents of array to which it is pointing to ! .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Let us see how it is done. See below * Step 1 : Define a single dimension array .. code-block:: c struct ABC { int a; int b; }; struct ABC a[3] = { {.a = 1, .b = 2}, {.a = 3, .b = 4}, {.a = 5, .b = 6} }; * Step 2 : Define a pointer to an array .. code-block:: c struct ABC (*ptr)[3]; * Step 3 : Let pointer to an array, point to single dimension array .. code-block:: c ptr = &a; .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow We can derive other rules from this base rule ! * Rule 1 : Base rule .. code-block:: c ptr = &a; * Rule 2 : Move ``&`` from RHS to LHS. This becomes ``*`` on LHS .. code-block:: c *ptr = a * Rule 3 : ``a`` is also equals to ``&a[0]`` .. code-block:: c *ptr = &a[0] * Rule 4 : ``*ptr`` is equal to ``ptr[0]`` .. code-block:: c ptr[0] = &a[0] * Rule 5 : Move ``&`` from RHS to LHS. This becomes ``*`` on LHS .. code-block:: c (*ptr)[0] = a[0] * Rule 6 : ``(*ptr)[0]`` is equal to ``ptr[0][0]`` .. code-block:: c ptr[0][0] = a[0] * Rule 7 : Extending Rule 5 .. code-block:: c (*ptr)[i] = a[i] * Step 4 : Access individual structures using ``(*ptr)[i]`` .. code-block:: c for (int i = 0; i < 3; i++) { printf("a = %d ", (*ptr)[i].a); printf("b = %d ", (*ptr)[i].b); printf("\n"); } * See full program below .. code-block:: c #include struct ABC { int a; int b; }; int main(void) { struct ABC a[3] = { {.a = 1, .b = 2}, {.a = 3, .b = 4}, {.a = 5, .b = 6} }; struct ABC (*ptr)[3]; ptr = &a; for (int i = 0; i < 3; i++) { printf("a = %d ", (*ptr)[i].a); printf("b = %d ", (*ptr)[i].b); printf("\n"); } return 0; } * Output is as below .. code-block:: c a = 1 b = 2 a = 3 b = 4 a = 5 b = 6 .. _ptr_to_array_struct_sp_ex_5: .. tab-set:: .. tab-item:: Method 2 : Pointer to an array : How to print contents of single dimension array ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow We can use pointer to an array directly inorder to print the contents of array to which it is pointing to ! .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Let us see how it is done. See below * Step 1 : Define a single dimension array .. code-block:: c struct ABC { int a; int b; }; struct ABC a[3] = { {.a = 1, .b = 2}, {.a = 3, .b = 4}, {.a = 5, .b = 6} }; * Step 2 : Pass address of array ``a`` as an argument to function ``fun`` .. code-block:: c fun(&a, sizeof(a) / sizeof(a[0]) ); * Step 3 : Define function ``fun`` .. code-block:: c void fun(struct ABC (*p)[3], int size) { } .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Note the function definition ! * Since first argument is passed as address of array ``a``, prototype must have pointer to an array in first parameter * Step 4 : Let us write the code to access individual structures of single dimension array inside function ``fun`` .. code-block:: c void fun(struct ABC (*p)[3], int size) { for (int i = 0; i < size; i++) { printf("(*p)[%d].a = %d\n", i, (*p)[i].a); printf("(*p)[%d].b = %d\n", i, (*p)[i].b); } for (int i = 0; i < size; i++) { printf("p[0][%d].a = %d\n", i, p[0][i].a); printf("p[0][%d].b = %d\n", i, p[0][i].b); } } .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow This is easy to understand ! Let us derive the rules * Rule 1 : Base rule .. code-block:: c p = &a Where, * LHS ``p`` is a variable on stack of function fun ``fun`` * RHS ``&a`` is actual argument passed to function ``fun`` * Rule 2 : Move ``&`` from RHS to LHS. This becomes ``*`` on LHS .. code-block:: c *p = a * Rule 3 : a is also equals to &a[0] .. code-block:: c *p = &a[0] * Rule 4 : Move ``&`` from RHS to LHS. This becomes ``*`` on LHS .. code-block:: c **p = a[0] * Rule 5 : ``*`` and ``[ ]`` can be used interchangeably .. code-block:: c (*p)[0] = a[0] * Rule 6 : ``*`` and ``[ ]`` can be used interchangeably .. code-block:: c p[0][0] = a[0] * Rule 7 : Extending Rule 5 .. code-block:: c (*p)[i] = a[i] * Rule 8 : Extending Rule 5 .. code-block:: c p[0][i] = a[i] * See full program below .. code-block:: c #include struct ABC { int a; int b; }; void fun(struct ABC (*p)[3], int size) { for (int i = 0; i < size; i++) { printf("(*p)[%d].a = %d\n", i, (*p)[i].a); printf("(*p)[%d].b = %d\n", i, (*p)[i].b); } for (int i = 0; i < size; i++) { printf("p[0][%d].a = %d\n", i, p[0][i].a); printf("p[0][%d].b = %d\n", i, p[0][i].b); } } int main(void) { struct ABC a[3] = { {.a = 1, .b = 2}, {.a = 3, .b = 4}, {.a = 5, .b = 6} }; fun(&a, sizeof(a) / sizeof(a[0]) ); return 0; } * Output is as below .. code-block:: c (*p)[0].a = 1 (*p)[0].b = 2 (*p)[1].a = 3 (*p)[1].b = 4 (*p)[2].a = 5 (*p)[2].b = 6 p[0][0].a = 1 p[0][0].b = 2 p[0][1].a = 3 p[0][1].b = 4 p[0][2].a = 5 p[0][2].b = 6 .. _ptr_to_array_struct_sp_ex_6: .. tab-set:: .. tab-item:: Pointer to an array : Pointing to Single dimension array inside a Double dimension array * Step 1 : Define a double dimension array of structures .. code-block:: c struct ABC a[2][3] = { { {.a = 1, .b = 2}, {.a = 3, .b = 4}, {.a = 5, .b = 6} }, { {.a = 100, .b = 200}, {.a = 300, .b = 400}, {.a = 500, .b = 600} }, }; * Step 2 : Define a pointer to an array of single dimension .. code-block:: c struct ABC (*ptr)[3]; * Step 3 : Let the pointer to point to Single dimension array inside a Double dimension array .. code-block:: c ptr = &a[0]; * See full program below .. code-block:: c #include struct ABC { int a; int b; }; int main(void) { struct ABC a[2][3] = { { {.a = 1, .b = 2}, {.a = 3, .b = 4}, {.a = 5, .b = 6} }, { {.a = 100, .b = 200}, {.a = 300, .b = 400}, {.a = 500, .b = 600} }, }; struct ABC (*ptr)[3]; ptr = &a[0]; for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { printf("ptr[%d][%d].a = %d\n", i, j, ptr[i][j].a); printf("ptr[%d][%d].b = %d\n", i, j, ptr[i][j].b); } } return 0; } * Output is as below .. code-block:: c ptr[0][0].a = 1 ptr[0][0].b = 2 ptr[0][1].a = 3 ptr[0][1].b = 4 ptr[0][2].a = 5 ptr[0][2].b = 6 ptr[1][0].a = 100 ptr[1][0].b = 200 ptr[1][1].a = 300 ptr[1][1].b = 400 ptr[1][2].a = 500 ptr[1][2].b = 600 .. _ptr_to_array_struct_sp_ex_7: .. tab-set:: .. tab-item:: Pointer to an array : Pointing to a block of memory in heap * Step 1 : Allocate a block of memory in Heap .. code-block:: c struct ABC *a; a = malloc(6 * sizeof(struct ABC)); * Step 2 : Assign User Data in Heap memory .. code-block:: c memset(a, 0xaa, 6 * sizeof(struct ABC)); * Step 3 : Let ``ptr`` point to block of memory in Heap .. code-block:: c struct ABC (*ptr)[3]; ptr = (struct ABC (*)[3]) a; .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Note that typecasting done ! .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Key is to remember that, ``ptr`` should point to block of continuous memory for it to access User data properly ! * Step 4 : Method 1 : Access the memory block in Heap using ``ptr`` .. code-block:: c for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { printf("ptr[%d][%d].a = %x\n", i, j, ptr[i][j].a); printf("ptr[%d][%d].b = %x\n", i, j, ptr[i][j].b); } } * Step 5 : Method 2 : Access the memory block in Heap using ``ptr`` .. code-block:: c for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { printf("*ptr->a = %x\n", (*ptr)->a); printf("*ptr->b = %x\n", (*ptr)->b); } ptr++; } .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Remember after Step 5, ``ptr`` is NOT pointing to start of Heap ! * Step 6 : Free Heap memory after use .. code-block:: c free(a); * See full program below .. code-block:: c #include #include #include struct ABC { int a; int b; }; int main(void) { struct ABC *a; struct ABC (*ptr)[3]; a = malloc(6 * sizeof(struct ABC)); memset(a, 0xaa, 6 * sizeof(struct ABC)); ptr = (struct ABC (*)[3])a; for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { printf("ptr[%d][%d].a = %x\n", i, j, ptr[i][j].a); printf("ptr[%d][%d].b = %x\n", i, j, ptr[i][j].b); } } for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { printf("*ptr->a = %x\n", (*ptr)->a); printf("*ptr->b = %x\n", (*ptr)->b); } ptr++; } free(a); return 0; } * Output is as below .. code-block:: c ptr[0][0].a = aaaaaaaa ptr[0][0].b = aaaaaaaa ptr[0][1].a = aaaaaaaa ptr[0][1].b = aaaaaaaa ptr[0][2].a = aaaaaaaa ptr[0][2].b = aaaaaaaa ptr[1][0].a = aaaaaaaa ptr[1][0].b = aaaaaaaa ptr[1][1].a = aaaaaaaa ptr[1][1].b = aaaaaaaa ptr[1][2].a = aaaaaaaa ptr[1][2].b = aaaaaaaa *ptr->a = aaaaaaaa *ptr->b = aaaaaaaa *ptr->a = aaaaaaaa *ptr->b = aaaaaaaa *ptr->a = aaaaaaaa *ptr->b = aaaaaaaa *ptr->a = aaaaaaaa *ptr->b = aaaaaaaa *ptr->a = aaaaaaaa *ptr->b = aaaaaaaa *ptr->a = aaaaaaaa *ptr->b = aaaaaaaa .. card:: See Also * Current Module * :doc:`../ptr_to_array` * Previous Module * :doc:`../../array_of_ptr/array_of_ptr` * Next Module * :doc:`../../function_ptr/function_ptr` * Other Modules * :doc:`../../variable_and_ptr/variable_and_ptr` * :doc:`../../array_n_ptrs/array_n_ptrs` * :doc:`../../malloc_ptr/malloc_ptr` * :doc:`../../typecasting_n_ptr/typecasting_n_ptr` * :doc:`../../funcs_n_ptrs/funcs_n_ptrs` * :doc:`../../memcpy_ptr/memcpy_ptr` * :doc:`../../const_ptr/const_ptr` * :doc:`../../void_ptr/void_ptr` * :doc:`../../pre_incr_ptr/pre_incr_ptr` * :doc:`../../post_incr_ptr/post_incr_ptr` * :doc:`../../pre_decr_ptr/pre_decr_ptr` * :doc:`../../post_decr_ptr/post_decr_ptr`