Pointer to a Double Dimension Array of Structures

In this section, you are going to learn

type ( *ptr ) [ row_size ] [ col_size ];

An example is as below

struct ABC {
        int a;
        int b;
};

struct ABC a[2][3] = {
        {
                {.a = 1, .b = 2},
                {.a = 3, .b = 4},
                {.a = 5, .b = 6},
        },
        {
                {.a = 10, .b = 20},
                {.a = 30, .b = 40},
                {.a = 50, .b = 60},
        },
};

struct ABC (*ptr)[2][3];

ptr = &a;

Pointer to an Array when incremented, increments by size of the array to which it is pointing to !

Pointer to an Array when decremented, decrements by size of the array to which it is pointing to !

Let us see how it is done. See below

  • Step 1 : Define a double dimension array

struct ABC {
        int a;
        int b;
};

struct ABC a[2][3] = {
        {
                {.a = 1, .b = 2},
                {.a = 3, .b = 4},
                {.a = 5, .b = 6},
        },
        {
                {.a = 10, .b = 20},
                {.a = 30, .b = 40},
                {.a = 50, .b = 60},
        },
};
  • Step 2 : Define a pointer to an array

struct ABC (*ptr)[2][3];
  • Step 3 : Let pointer to an array, point to double dimension array

ptr = &a;
  • Step 4 : Check pointer arithmetic

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

#include <stdio.h>

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 = 10, .b = 20},
                        {.a = 30, .b = 40},
                        {.a = 50, .b = 60},
                },
        };

        struct ABC (*ptr)[2][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

Before Increment : ptr = 7fff70176280
After  Increment : ptr = 7fff701762b0

Observe that difference is 48 !

  • Size of two dimensional array is 48 Bytes

  • Hence incrementing ptr will increment by 48 Bytes

When Pointer to an Array is passed as argument, Prototype of function should match the type properly !

Let us see how it is done. See below

  • Step 1 : Define a double dimension array

struct ABC {
        int a;
        int b;
};

struct ABC a[2][3] = {
        {
                {.a = 1, .b = 2},
                {.a = 3, .b = 4},
                {.a = 5, .b = 6},
        },
        {
                {.a = 10, .b = 20},
                {.a = 30, .b = 40},
                {.a = 50, .b = 60},
        },
};
  • Step 2 : Define a pointer to an array

struct ABC (*ptr)[2][3];
  • Step 3 : Let pointer to an array, point to double dimension array

ptr = &a;
  • Step 4 : Pass ptr as argument to function fun

fun(ptr);
  • Step 5 : Define function fun

void fun( struct ABC (*p)[2][3] )
{
}
  • Step 6 : Print individual structures inside fun

void fun( struct ABC (*p)[2][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");
        }
}

This is easy to understand ! Let us derive the rules

  • Rule 1 : Base Rule inside main

ptr = &a
  • Rule 2 : Base Rule inside fun

p = ptr
  • Rule 3 : From Rule 1 and Rule 2

p = &a
  • Rule 4 : Move & from RHS to LHS. This becomes * on LHS

*p = a;
  • Rule 5 : a is equal to &a[0]

*p = &a[0]
  • Rule 6 : Move & from RHS to LHS. This becomes * on LHS

**p = a[0]
  • Rule 7 : * and [ ] can be used interchangeably

(*p)[0] = a[0]
  • Rule 8 : Extending Rule 7

(*p)[i] = a[i]
  • Rule 9 : a[0] is equal to &a[0][0]

(*p)[0] = &a[0][0]
  • Rule 10 : Move & from RHS to LHS. This becomes * on LHS

(**p)[0] = a[0][0]
  • Rule 11 : * and [ ] can be used interchangeably

(*p)[0][0] = a[0][0]
  • Rule 12 : Extending Rule 11

(*p)[i][j] = a[i][j]

Hence we proved, if a[i][j] is an structure then (*p)[i][j] is also an structure

Another way to understand !

  • int (*p)[2][4] is the declaration of pointer p

  • (*p)[ ][ ] is dereferenced to maximum level. Hence is an structure

  • See full program below

#include <stdio.h>

struct ABC {
        int a;
        int b;
};

void fun( struct ABC (*p)[2][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 = 10, .b = 20},
                        {.a = 30, .b = 40},
                        {.a = 50, .b = 60},
                },
        };

        struct ABC (*ptr)[2][3];

        ptr = &a;

        fun(ptr);

        return 0;
}
  • Output is as below

(*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 = 10 (*p)[1][0].b = 20
(*p)[1][1].a = 30 (*p)[1][1].b = 40
(*p)[1][2].a = 50 (*p)[1][2].b = 60

When Pointer to an Array is passed as argument by call by reference, Prototype of function should match the type properly !

Let us see how it is done. See below

  • Step 1 : Define a Double dimension array

struct ABC {
        int a;
        int b;
};

struct ABC a[2][3] = {
        {
                {.a = 1, .b = 2},
                {.a = 3, .b = 4},
                {.a = 5, .b = 6},
        },
        {
                {.a = 10, .b = 20},
                {.a = 30, .b = 40},
                {.a = 50, .b = 60},
        },
};
  • Step 2 : Define a pointer to an array

struct ABC (*ptr)[2][3];
  • Step 3 : Let pointer to an array, point to double dimension array

ptr = &a;
  • Step 4 : Pass ptr as argument to function fun. Call by reference

fun(&ptr);
  • Step 5 : Define function fun and print individual structures

void fun(struct ABC (**p)[2][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");
        }
}

This is easy to understand ! Let us derive the rules

  • Rule 1 : Base rule in main

ptr = &a;
  • Rule 2 : Base rule in fun

p = &ptr
  • Rule 2 : Move & from RHS to LHS. This becomes * on LHS

*p = ptr
  • Rule 3 : Replace ptr referring to Rule 1

*p = &a
  • Rule 4 : Move & from RHS to LHS. This becomes * on LHS

**p = a
  • Rule 5 : * and [ ] can be used interchangeably

(*p)[0] = a
  • Rule 6 : a is equal to &a[0]

(*p)[0] = &a[0]
  • Rule 7 : Move & from RHS to LHS. This becomes * on LHS

(**p)[0] = a[0]
  • Rule 8 : Extending Rule 7

(**p)[i] = a[i]
  • Rule 9 : a[0] is equal to &a[0][0]

(**p)[0] = &a[0][0]
  • Rule 10 : Move & from RHS to LHS. This becomes * on LHS

(***p)[0] = a[0][0]
  • Rule 11 : * and [ ] can be used interchangeably

(**p)[0][0] = a[0][0]
  • Rule 12 : Extending Rule 11

(**p)[i][j] = a[i][j]

Hence we proved if a[i][j] is a structure then (**p)[i][j] is also a structure

  • See full program below

#include <stdio.h>

struct ABC {
        int a;
        int b;
};

void fun(struct ABC (**p)[2][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 = 10, .b = 20},
                        {.a = 30, .b = 40},
                        {.a = 50, .b = 60},
                },
        };

        struct ABC (*ptr)[2][3];

        ptr = &a;

        fun(&ptr);

        return 0;
}
  • Output is as below

(**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 = 10 (**p)[1][0].b = 20
(**p)[1][1].a = 30 (**p)[1][1].b = 40
(**p)[1][2].a = 50 (**p)[1][2].b = 60
  • Step 1 : Define a triple dimension array of structures

struct ABC {
        int a;
        int b;
};

struct ABC a[2][2][2] = {
        {
                {
                        {.a = 1, .b = 2},
                        {.a = 3, .b = 4},
                },
                {
                        {.a = 10, .b = 20},
                        {.a = 30, .b = 40},
                },
        },
        {
                {
                        {.a = 100, .b = 200},
                        {.a = 300, .b = 400},
                },
                {
                        {.a = 1000, .b = 2000},
                        {.a = 3000, .b = 4000},
                },
        }
};
  • Step 2 : Define a pointer to an array of double dimension

struct ABC (*ptr)[2][2];
  • Step 3 : Let the pointer to point to Double dimension array inside a Double dimension array

ptr = &a[0];
  • Step 4 : Print the individual structures

for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
                for (int k = 0; k < 2; k++) {
                        printf("(*ptr)[%d][%d][%d].a = %d ", i, j, k, ptr[i][j][k].a);
                        printf("(*ptr)[%d][%d][%d].b = %d ", i, j, k, ptr[i][j][k].b);
                        printf("\n");
                }
        }
        printf("\n");
}

This is easy to understand ! Let us derive the rules

  • Rule 1 : Base rule

ptr = &a[0];
  • Rule 2 : Move & from RHS to LHS. This becomes * on LHS

*ptr = a[0]
  • Rule 3 : a[0] is equal to &a[0][0]

*ptr = &a[0][0]
  • Rule 4 : Move & from RHS to LHS. This becomes * on LHS

**ptr = a[0][0]
  • Rule 5 : * and [ ] can be used interchangeably

ptr[0][0] = a[0][0]
  • Rule 6 : Extending Rule 3

ptr[i][j] = a[i][j]
  • Rule 7 : a[0][0] is equal to &a[0][0][0]

ptr[0][0] = &a[0][0][0]
  • Rule 8 : Move & from RHS to LHS. This becomes * on LHS

*ptr[0][0] = a[0][0][0]
  • Rule 9 : * and [ ] can be used interchangeably

ptr[0][0][0] = a[0][0][0]
  • Rule 10 : Extending Rule 9

ptr[i][j][k] = a[i][j][k]

Hence we proved, if a[i][j][k] is a structure then p[i][j][k] is also also a structure

  • See full program below

#include <stdio.h>

struct ABC {
        int a;
        int b;
};

int main(void)
{
        struct ABC a[2][2][2] = {
                {
                        {
                                {.a = 1, .b = 2},
                                {.a = 3, .b = 4},
                        },
                        {
                                {.a = 10, .b = 20},
                                {.a = 30, .b = 40},
                        },
                },
                {
                        {
                                {.a = 100, .b = 200},
                                {.a = 300, .b = 400},
                        },
                        {
                                {.a = 1000, .b = 2000},
                                {.a = 3000, .b = 4000},
                        },
                }
        };

        struct ABC (*ptr)[2][2];

        ptr = &a[0];

        for (int i = 0; i < 2; i++) {
                for (int j = 0; j < 2; j++) {
                        for (int k = 0; k < 2; k++) {
                                printf("(*ptr)[%d][%d][%d].a = %d ", i, j, k, ptr[i][j][k].a);
                                printf("(*ptr)[%d][%d][%d].b = %d ", i, j, k, ptr[i][j][k].b);
                                printf("\n");
                        }
                }
                printf("\n");
        }

        return 0;
}
  • Output is as below

(*ptr)[0][0][0].a = 1 (*ptr)[0][0][0].b = 2
(*ptr)[0][0][1].a = 3 (*ptr)[0][0][1].b = 4
(*ptr)[0][1][0].a = 10 (*ptr)[0][1][0].b = 20
(*ptr)[0][1][1].a = 30 (*ptr)[0][1][1].b = 40

(*ptr)[1][0][0].a = 100 (*ptr)[1][0][0].b = 200
(*ptr)[1][0][1].a = 300 (*ptr)[1][0][1].b = 400
(*ptr)[1][1][0].a = 1000 (*ptr)[1][1][0].b = 2000
(*ptr)[1][1][1].a = 3000 (*ptr)[1][1][1].b = 4000