Basics of Structure Triple Pointers

In this section, you are going to learn

  • Step 1 : Define a Structure

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

struct ABC x = { .a = 1, .b = 2, .c = 3 };
  • Step 2 : Define a Single pointer

struct ABC *sp = &x;

OR

struct ABC *sp;

sp = &x;
  • Step 3 : Define a Double pointer

struct ABC **dp = &sp;

OR

struct ABC **dp;

dp = &sp;
  • Step 4 : Define a Triple pointer

struct ABC ***tp = &dp;

OR

struct ABC ***tp;

tp = &dp;
  • Step 5 : Access user data (in this case structure) using single pointer

printf("sp->a = %d\n", sp->a);
printf("sp->b = %d\n", sp->b);
printf("sp->c = %d\n", sp->c);
  • Step 6 : Access user data (in this case structure) using double pointer

printf("(*dp)->a = %d\n", (*dp)->a);
printf("(*dp)->b = %d\n", (*dp)->b);
printf("(*dp)->c = %d\n", (*dp)->c);
  • Step 7 : Access user data (in this case structure) using triple pointer

printf("(**tp)->a = %d\n", (**tp)->a);
printf("(**tp)->b = %d\n", (**tp)->b);
printf("(**tp)->c = %d\n", (**tp)->c);
  • See full program below

#include <stdio.h>

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

int main(void)
{
        struct ABC x = { .a = 1, .b = 2, .c = 3 };

        struct ABC *sp;
        sp = &x;

        struct ABC **dp;
        dp = &sp;

        struct ABC ***tp;
        tp = &dp;

        printf("sp->a = %d\n", sp->a);
        printf("sp->b = %d\n", sp->b);
        printf("sp->c = %d\n", sp->c);

        printf("(*dp)->a = %d\n", (*dp)->a);
        printf("(*dp)->b = %d\n", (*dp)->b);
        printf("(*dp)->c = %d\n", (*dp)->c);

        printf("(**tp)->a = %d\n", (**tp)->a);
        printf("(**tp)->b = %d\n", (**tp)->b);
        printf("(**tp)->c = %d\n", (**tp)->c);

        return 0;
}
  • Output is as below

sp->a = 1
sp->b = 2
sp->c = 3

(*dp)->a = 1
(*dp)->b = 2
(*dp)->c = 3

(**tp)->a = 1
(**tp)->b = 2
(**tp)->c = 3

Summary of Naming conventions

Consider

struct ABC ***tp;

then

  • tp is a triple pointer

  • *tp is a double pointer

  • **tp is a single pointer

  • ***tp is user data

  • Step 1 : Define a single dimension array of structures

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

struct ABC arr[3] = {
        { .a = 1, .b = 2, .c = 3 },
        { .a = 10, .b = 20, .c = 30 },
        { .a = 100, .b = 200, .c = 300 },
};
  • Step 2 : Define a single pointer

struct ABC *sp = arr;

OR

struct ABC *sp;

sp = arr;

OR

struct ABC *sp;

sp = &arr[0];
  • Step 3 : Define a double pointer

struct ABC **dp = &sp;

OR

struct ABC **dp;

dp = &sp;
  • Step 4 : Define a Triple pointer

struct ABC ***tp = &dp;

OR

struct ABC ***tp;

tp = &dp;
  • Step 5 : Access user data (in this case array of structures) using single pointer variable arr

for (int i = 0 ; i < sizeof(arr)/sizeof(arr[0]); i++)
{
        printf("arr[%d].a = %d\n", i, arr[i].a);
        printf("arr[%d].b = %d\n", i, arr[i].b);
        printf("arr[%d].c = %d\n", i, arr[i].c);
}
  • Step 5 : Access user data (in this case array of structures) using single pointer variable sp

for (int i = 0 ; i < sizeof(arr)/sizeof(arr[0]); i++)
{
        printf("sp[%d].a = %d\n", i, sp[i].a);
        printf("sp[%d].b = %d\n", i, sp[i].b);
        printf("sp[%d].c = %d\n", i, sp[i].c);
}
  • Step 6 : Access user data (in this case array of structures) using double pointer variable dp

for (int i = 0 ; i < sizeof(arr)/sizeof(arr[0]); i++)
{
        printf("(*dp)[%d].a = %d\n", i, (*dp)[i].a);
        printf("(*dp)[%d].b = %d\n", i, (*dp)[i].b);
        printf("(*dp)[%d].c = %d\n", i, (*dp)[i].c);
}
  • Step 7 : Access user data (in this case array of structures) using triple pointer variable tp

for (int i = 0 ; i < sizeof(arr)/sizeof(arr[0]); i++)
{
        printf("(**tp)[%d].a = %d\n", i, (**tp)[i].a);
        printf("(**tp)[%d].b = %d\n", i, (**tp)[i].b);
        printf("(**tp)[%d].c = %d\n", i, (**tp)[i].c);
}

Note *dp should be called as single pointer because of below equations

  • dp = &sp;

  • *dp = sp;

Note **tp should be called as single pointer because of below equations

  • tp = &dp;

  • *tp = dp;

  • *tp = &sp;

  • **tp = sp;

  • See full program below

#include <stdio.h>

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

int main(void)
{
        struct ABC arr[3] = {
                { .a = 1, .b = 2, .c = 3 },
                { .a = 10, .b = 20, .c = 30 },
                { .a = 100, .b = 200, .c = 300 },
        };

        struct ABC *sp;
        sp = arr;

        struct ABC **dp;
        dp = &sp;

        struct ABC ***tp;
        tp = &dp;

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

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

        for (int i = 0 ; i < sizeof(arr)/sizeof(arr[0]); i++)
        {
                printf("(*dp)[%d].a = %d\n", i, (*dp)[i].a);
                printf("(*dp)[%d].b = %d\n", i, (*dp)[i].b);
                printf("(*dp)[%d].c = %d\n", i, (*dp)[i].c);
        }

        for (int i = 0 ; i < sizeof(arr)/sizeof(arr[0]); i++)
        {
                printf("(**tp)[%d].a = %d\n", i, (**tp)[i].a);
                printf("(**tp)[%d].b = %d\n", i, (**tp)[i].b);
                printf("(**tp)[%d].c = %d\n", i, (**tp)[i].c);
        }

        return 0;
}
  • Output is as below

arr[0].a = 1
arr[0].b = 2
arr[0].c = 3
arr[1].a = 10
arr[1].b = 20
arr[1].c = 30
arr[2].a = 100
arr[2].b = 200
arr[2].c = 300

sp[0].a = 1
sp[0].b = 2
sp[0].c = 3
sp[1].a = 10
sp[1].b = 20
sp[1].c = 30
sp[2].a = 100
sp[2].b = 200
sp[2].c = 300

(*dp)[0].a = 1
(*dp)[0].b = 2
(*dp)[0].c = 3
(*dp)[1].a = 10
(*dp)[1].b = 20
(*dp)[1].c = 30
(*dp)[2].a = 100
(*dp)[2].b = 200
(*dp)[2].c = 300

(**tp)[0].a = 1
(**tp)[0].b = 2
(**tp)[0].c = 3
(**tp)[1].a = 10
(**tp)[1].b = 20
(**tp)[1].c = 30
(**tp)[2].a = 100
(**tp)[2].b = 200
(**tp)[2].c = 300
  • Step 1 : Define a single pointer

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

struct ABC *sp;
  • Step 2 : Allocate heap memory to single pointer

sp = malloc(3 * sizeof(struct ABC));
  • Step 3 : Copy User data to heap memory

sp[0].a = 1;
sp[0].b = 2;
sp[0].c = 3;

sp[1].a = 10;
sp[1].b = 20;
sp[1].c = 30;

sp[2].a = 100;
sp[2].b = 200;
sp[2].c = 300;
  • Step 4 : Define a double pointer

struct ABC **dp;
dp = &sp;
  • Step 5 : Define a Triple pointer

struct ABC ***tp = &dp;

OR

struct ABC ***tp;

tp = &dp;
  • Step 6 : Access User data using single pointer variable sp

for (int i = 0 ; i < sizeof(arr)/sizeof(arr[0]); i++)
{
        printf("sp[%d].a = %d\n", i, sp[i].a);
        printf("sp[%d].b = %d\n", i, sp[i].b);
        printf("sp[%d].c = %d\n", i, sp[i].c);
}
  • Step 7 : Access User data using double pointer variable dp

for (int i = 0 ; i < sizeof(arr)/sizeof(arr[0]); i++)
{
        printf("(*dp)[%d].a = %d\n", i, (*dp)[i].a);
        printf("(*dp)[%d].b = %d\n", i, (*dp)[i].b);
        printf("(*dp)[%d].c = %d\n", i, (*dp)[i].c);
}
  • Step 8 : Access User data using triple pointer variable tp

for (int i = 0 ; i < sizeof(arr)/sizeof(arr[0]); i++)
{
        printf("(**tp)[%d].a = %d\n", i, (**tp)[i].a);
        printf("(**tp)[%d].b = %d\n", i, (**tp)[i].b);
        printf("(**tp)[%d].c = %d\n", i, (**tp)[i].c);
}
  • Step 9 : Free memory after usage

free(sp);

OR

free(*dp);

OR

free(**tp);
  • See full program below

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

int main(void)
{
        struct ABC *sp;

        sp = malloc(3 * sizeof(struct ABC));

        sp[0].a = 1;
        sp[0].b = 2;
        sp[0].c = 3;

        sp[1].a = 10;
        sp[1].b = 20;
        sp[1].c = 30;

        sp[2].a = 100;
        sp[2].b = 200;
        sp[2].c = 300;

        struct ABC **dp;
        dp = &sp;

        struct ABC ***tp;
        tp = &dp;

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

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

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

        free(sp);

        return 0;
}
  • Output is as below

sp[0].a = 1
sp[0].b = 2
sp[0].c = 3
sp[1].a = 10
sp[1].b = 20
sp[1].c = 30
sp[2].a = 100
sp[2].b = 200
sp[2].c = 300

(*dp)[0].a = 1
(*dp)[0].b = 2
(*dp)[0].c = 3
(*dp)[1].a = 10
(*dp)[1].b = 20
(*dp)[1].c = 30
(*dp)[2].a = 100
(*dp)[2].b = 200
(*dp)[2].c = 300

(**tp)[0].a = 1
(**tp)[0].b = 2
(**tp)[0].c = 3
(**tp)[1].a = 10
(**tp)[1].b = 20
(**tp)[1].c = 30
(**tp)[2].a = 100
(**tp)[2].b = 200
(**tp)[2].c = 300
  • Step 1 : Define a double pointer

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

struct ABC **dp;
  • Step 2 : Allocate memory to a double pointer

dp = malloc(sizeof(struct ABC *));
  • Step 3 : Allocate memory to a single pointer

*dp = malloc(sizeof(struct ABC));
  • Step 4 : Store user data

(*dp)->a = 1;
(*dp)->b = 2;
(*dp)->c = 3;
  • Step 5 : Define a Triple pointer

struct ABC ***tp = &dp;

OR

struct ABC ***tp;

tp = &dp;
  • Step 6 : Read user data using dp

printf("(*dp)->a = %d\n", (*dp)->a);
printf("(*dp)->b = %d\n", (*dp)->b);
printf("(*dp)->c = %d\n", (*dp)->c);
  • Step 7 : Read user data using tp

printf("(**tp)->a = %d\n", (**tp)->a);
printf("(**tp)->b = %d\n", (**tp)->b);
printf("(**tp)->c = %d\n", (**tp)->c);
  • Step 8 : Free memory in opposite flow of allocation

free(*dp);

free(dp);

OR

free(**tp);

free(*tp);
  • See full program below

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

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

int main(void)
{
        struct ABC **dp;

        dp = malloc(sizeof(struct ABC *));

        *dp = malloc(sizeof(struct ABC));

        (*dp)->a = 1;
        (*dp)->b = 2;
        (*dp)->c = 3;

        printf("(*dp)->a = %d\n", (*dp)->a);
        printf("(*dp)->b = %d\n", (*dp)->b);
        printf("(*dp)->c = %d\n", (*dp)->c);

        struct ABC ***tp;
        tp = &dp;

        printf("(**tp)->a = %d\n", (**tp)->a);
        printf("(**tp)->b = %d\n", (**tp)->b);
        printf("(**tp)->c = %d\n", (**tp)->c);

        free(*dp); // or free(**tp);

        free(dp);  // or free(*tp);

        return 0;
}
  • Output is as below

(*dp)->a = 1
(*dp)->b = 2
(*dp)->c = 3

(**tp)->a = 1
(**tp)->b = 2
(**tp)->c = 3
  • Step 1 : Define a double pointer

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

struct ABC **dp;
  • Step 2 : Allocate memory to a double pointer

dp = malloc(sizeof(struct ABC *));
  • Step 3 : Allocate memory to a single pointer

*dp = malloc(3 * sizeof(struct ABC));
  • Step 4 : Copy User data to heap

(*dp)[0].a = 1;
(*dp)[0].b = 2;
(*dp)[0].c = 3;

(*dp)[1].a = 10;
(*dp)[1].b = 20;
(*dp)[1].c = 30;

(*dp)[2].a = 100;
(*dp)[2].b = 200;
(*dp)[2].c = 300;
  • Step 5 : Define a Triple pointer

struct ABC ***tp = &dp;

OR

struct ABC ***tp;

tp = &dp;
  • Step 6 : Read user data from heap using dp

for (int i = 0; i < 3; i++) {
        printf("(*dp)[%d].a = %d\n", i, (*dp)[i].a );
        printf("(*dp)[%d].b = %d\n", i, (*dp)[i].b );
        printf("(*dp)[%d].c = %d\n", i, (*dp)[i].c );
}
  • Step 7 : Read user data from heap using tp

for (int i = 0; i < 3; i++) {
        printf("(**tp)[%d].a = %d\n", i, (**tp)[i].a );
        printf("(**tp)[%d].b = %d\n", i, (**tp)[i].b );
        printf("(**tp)[%d].c = %d\n", i, (**tp)[i].c );
}
  • Step 6 : Free memory in opposite flow of allocation

free(*dp);

free(dp);

OR

free(**tp);

free(*tp);
  • See full program below

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

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

int main(void)
{
        struct ABC **dp;

        dp = malloc(sizeof(struct ABC *));

        *dp = malloc(3 * sizeof(struct ABC));

        (*dp)[0].a = 1;
        (*dp)[0].b = 2;
        (*dp)[0].c = 3;

        (*dp)[1].a = 10;
        (*dp)[1].b = 20;
        (*dp)[1].c = 30;

        (*dp)[2].a = 100;
        (*dp)[2].b = 200;
        (*dp)[2].c = 300;

        struct ABC ***tp;

        tp = &dp;

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

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

        free(*dp); // or free(**tp);

        free(dp);  // or free(*tp);

        return 0;
}
  • Output is as below

(*dp)[0].a = 1
(*dp)[0].b = 2
(*dp)[0].c = 3
(*dp)[1].a = 10
(*dp)[1].b = 20
(*dp)[1].c = 30
(*dp)[2].a = 100
(*dp)[2].b = 200
(*dp)[2].c = 300

(**tp)[0].a = 1
(**tp)[0].b = 2
(**tp)[0].c = 3
(**tp)[1].a = 10
(**tp)[1].b = 20
(**tp)[1].c = 30
(**tp)[2].a = 100
(**tp)[2].b = 200
(**tp)[2].c = 300
  • Step 1 : Define a double pointer

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

struct ABC **dp;
  • Step 2 : Allocate heap memory : Create 2 single pointers dp[0], dp[1]

dp = malloc(2 * sizeof(struct ABC *));
  • Step 3 : Allocate heap memory : Create 2 single dimension structure arrays of size 3 structures each

dp[0] = malloc(3 * sizeof(struct ABC));
dp[1] = malloc(3 * sizeof(struct ABC));
  • Step 4 : Store user data

dp[0][0].a = 1;
dp[0][0].b = 2;
dp[0][0].c = 3;

dp[0][1].a = 4;
dp[0][1].b = 5;
dp[0][1].c = 6;

dp[0][2].a = 7;
dp[0][2].b = 8;
dp[0][2].c = 9;

dp[1][0].a = 10;
dp[1][0].b = 11;
dp[1][0].c = 12;

dp[1][1].a = 13;
dp[1][1].b = 14;
dp[1][1].c = 15;

dp[1][2].a = 16;
dp[1][2].b = 17;
dp[1][2].c = 18;
  • Step 5 : Define a Triple pointer

struct ABC ***tp = &dp;

OR

struct ABC ***tp;

tp = &dp;
  • Step 6 : Access user data using dp

for (int i = 0 ; i < 2; i++)
{
        for (int j = 0; j < 3; j++)
        {
                printf("dp[%d][%d].a = %d\n", i, j, dp[i][j].a );
                printf("dp[%d][%d].b = %d\n", i, j, dp[i][j].b );
                printf("dp[%d][%d].c = %d\n", i, j, dp[i][j].c );
        }
}
  • Step 7 : Access user data using tp

for (int i = 0 ; i < 2; i++)
{
        for (int j = 0; j < 3; j++)
        {
                printf("(*tp)[%d][%d].a = %d\n", i, j, (*tp)[i][j].a );
                printf("(*tp)[%d][%d].b = %d\n", i, j, (*tp)[i][j].b );
                printf("(*tp)[%d][%d].c = %d\n", i, j, (*tp)[i][j].c );
        }
}
  • Step 6 : Free 2 structure arrays

free(dp[0]);
free(dp[1]);

OR

free((*tp)[0]);
free((*tp)[1]);
  • Step 7 : Free 2 single pointers

free(dp);
  • See full program below

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

int main(void)
{
        struct ABC **dp;

        dp = malloc(2 * sizeof(struct ABC *));

        dp[0] = malloc(3 * sizeof(struct ABC));
        dp[1] = malloc(3 * sizeof(struct ABC));

        dp[0][0].a = 1;
        dp[0][0].b = 2;
        dp[0][0].c = 3;

        dp[0][1].a = 4;
        dp[0][1].b = 5;
        dp[0][1].c = 6;

        dp[0][2].a = 7;
        dp[0][2].b = 8;
        dp[0][2].c = 9;

        dp[1][0].a = 10;
        dp[1][0].b = 11;
        dp[1][0].c = 12;

        dp[1][1].a = 13;
        dp[1][1].b = 14;
        dp[1][1].c = 15;

        dp[1][2].a = 16;
        dp[1][2].b = 17;
        dp[1][2].c = 18;

        struct ABC ***tp;

        tp = &dp;

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

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

        free(dp[0]);
        free(dp[1]);

        free(dp);

        return 0;
}
  • Output as is below

dp[0][0].a = 1
dp[0][0].b = 2
dp[0][0].c = 3
dp[0][1].a = 4
dp[0][1].b = 5
dp[0][1].c = 6
dp[0][2].a = 7
dp[0][2].b = 8
dp[0][2].c = 9
dp[1][0].a = 10
dp[1][0].b = 11
dp[1][0].c = 12
dp[1][1].a = 13
dp[1][1].b = 14
dp[1][1].c = 15
dp[1][2].a = 16
dp[1][2].b = 17
dp[1][2].c = 18

(*tp)[0][0].a = 1
(*tp)[0][0].b = 2
(*tp)[0][0].c = 3
(*tp)[0][1].a = 4
(*tp)[0][1].b = 5
(*tp)[0][1].c = 6
(*tp)[0][2].a = 7
(*tp)[0][2].b = 8
(*tp)[0][2].c = 9
(*tp)[1][0].a = 10
(*tp)[1][0].b = 11
(*tp)[1][0].c = 12
(*tp)[1][1].a = 13
(*tp)[1][1].b = 14
(*tp)[1][1].c = 15
(*tp)[1][2].a = 16
(*tp)[1][2].b = 17
(*tp)[1][2].c = 18