2

I have this int **i or int ***i or int ****k

how to assign value and to do printf to/of i, j and k?

also if I have

 struct abc { int *i; int **j; int ***k; };

then how to assign and print values to i, j, k if I have

  struct abc *b = ...;
  struct abc **c = ...;
  struct abc ***d = ...;

I assume malloc will never be needed.

update

I tried like this

int *i=malloc(sizeof(int)*2);
i[0]=5;
int **j=(int **)i;
int ***k=(int ***)j;
printf("%d\n",k[0][0][0]);

but at printf it throws segFault

And also

int *a=malloc(sizeof(int)*3);
int *b=malloc(sizeof(int)*3);
int *c=malloc(sizeof (int) *3);
int **i={a,b,c};
i[0]=a;
i[1]=b;
i[2]=c;
i[0][0]=5;
printf("%d\n",i[0][0]);

again segFault at printf

Update

and how to call scanf and pass i, j and k, and abc like in chqrlie answer ? and if I have a function like

void call_this(struct abc ***d)
{
   //how to assign and print
}
user786
  • 3,902
  • 4
  • 40
  • 72
  • just need to know how to handle `dereference` operator in code – user786 May 12 '21 at 06:43
  • Don't comment your own question but [edit] the question and put all clarifications _there_. – Jabberwocky May 12 '21 at 06:46
  • Start with `int *i;` that is a *pointer-to* `int`. You allocate a block of memory holding however many `int` you want and assign the starting address to the pointer `i`. `int **j;` is a *pointer-to-pointer-to* `int`. You allocate a block holding however many pointers (rows) you want, and then for each row-pointer you allocate and assign a block holding however many `int` you need. Each level of indirection is removed by dereference, using either `'*'` or `[..]`. `j` can be indexed as a simulated 2D array as `j[x][y]` to get the `int` in row `x` col `y`, and so on... – David C. Rankin May 12 '21 at 06:54
  • See for discussion, e.g. [How to allocate the memory dynamically for multi dimensional arrays](https://stackoverflow.com/a/67295070/3422102) – David C. Rankin May 12 '21 at 06:56
  • @Jabberwocky is there a way to access with `dereference` operator – user786 May 12 '21 at 07:03
  • @Jabberwocky `int ***i=malloc(sizeof(int)*10);i[0][0][0]=5;printf("%d\n",i[0][0][0]);` throws segFault – user786 May 12 '21 at 07:10
  • Maybe you should tell us what you are _actually_ trying to achieve. This looks like an [XY Problem](https://en.wikipedia.org/wiki/XY_problem) – Jabberwocky May 12 '21 at 07:12
  • 1
    You can NOT cast levels of indirection. (e.g. `int **j=(int **)i;`) Levels of indirection invariant, they are a simple state or property. You can take the address of a variable to add a level of indirection, or dereference to remove a level. That's it. – David C. Rankin May 12 '21 at 07:25

2 Answers2

4

Here is an example without any malloc() calls:

#include <stdio.h>

struct abc { int *i; int **j; int ***k; };

int main() {
    int n;
    int *p = &n;
    int **pp = &p;
    int ***ppp = &pp;
    struct abc a = { p, pp, ppp };
    struct abc *b = &a;
    struct abc **c = &b;
    struct abc ***d = &c;

    n = 42;
    // all expressions ulimately point to the same integer
    printf("          n=%d\n", n);
    printf("         *p=%d\n", *p);
    printf("       **pp=%d\n", **pp);
    printf("     ***ppp=%d\n", ***ppp);
    printf("       *a.i=%d\n", *a.i);
    printf("    *(*b).i=%d\n", *(*b).i);        // same as *b->i
    printf("   *(**c).i=%d\n", *(**c).i);       // same as *(*c)->i
    printf("  *(***d).i=%d\n", *(***d).i);      // same as *(**d)->i
    printf("      **a.j=%d\n", **a.j);
    printf("   **(*b).j=%d\n", **(*b).j);       // same as **b->j
    printf("  **(**c).j=%d\n", **(**c).j);      // same as **(*c)->j
    printf(" **(***d).j=%d\n", **(***d).j);     // same as **(**d)->j
    printf("     ***a.k=%d\n", ***a.k);
    printf("  ***(*b).k=%d\n", ***(*b).k);      // same as ***b->k
    printf(" ***(**c).k=%d\n", ***(**c).k);     // same as ***(*c)->k
    printf("***(***d).k=%d\n", ***(***d).k);    // same as ***(**d)->k
    return 0;
}

Output:

          n=42
         *p=42
       **pp=42
     ***ppp=42
       *a.i=42
    *(*b).i=42
   *(**c).i=42
  *(***d).i=42
      **a.j=42
   **(*b).j=42
  **(**c).j=42
 **(***d).j=42
     ***a.k=42
  ***(*b).k=42
 ***(**c).k=42
***(***d).k=42

The parentheses in the above expressions are required because of precedence rules. Postfix unary operators are applied first from left to right, then prefix unary operators are applied from right to left. ***(***d).k is parsed as *(*(*(*(*(*d))).k)), which is even less readable.

Note however that it is considered bad style to use triple indirections, that are rarely needed in practice. Don't be a 3 star programmer

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 3
    The sheer creativity involved gets a nod `:)` – David C. Rankin May 12 '21 at 07:27
  • thanks for ur answer. can u also show how to call scanf and pass like u showed with printf. thanks – user786 Oct 01 '21 at 09:54
  • can u please see the updated question. thanks – user786 Oct 01 '21 at 09:59
  • @user786: your question updates have undefined behavior because `int **j=(int **)i; int ***k=(int ***)j;` initialize `k` as a triple pointer, but with the value of `i` which is just a pointer to `int`. Dereferencing `***k`, which is the same as `k[0][0][0]` attempts to dereference an `int` as a pointer, which is invalid. – chqrlie Oct 01 '21 at 20:01
  • @user786: For the second update: `int **i={a,b,c};` should issue a diagnostic because you initialize a single pointer `i` from an initializer with 3 values, and the first value has a different incompatible type. Furthermore, `i[0] = a;` will dereference `i` as a pointer to a pointer, whereas its value is just a pointer to `int`. Undefined behavior again. – chqrlie Oct 01 '21 at 20:06
  • @user786: the third update is off topic. You should ask new questions instead of updating existing ones with unrelated points. – chqrlie Oct 01 '21 at 20:07
0

First we need to create object to assign addresses to that b, c and d variables

struct abc a; // create empty object

int tmp = 1; // create int to store it's address in a

a.i = &tmp; // store address of tmp in i
a.j = &a.i; // store address of i in j
a.k = &a.j; // store address of j in k

Then we can assign a's reference to b

struct abc *b = &a;

Then to c and d

struct abc **c = &b;
struct abc *** d = &c;

Now we have 1 object a and have direct address it via b, also we have direct address to b via c and so on...

We can also access a from c. First we need to get address of b

printf("%p", c); // address of b
printf("%p", *c); // address of a

struct abc a_cpy = **c; // create copy of object a
printf("%p", a_cpy.i); // address that was stored in the copy of a
Luka Samkharadze
  • 111
  • 1
  • 12