0

I want to declare Pointer ptr0 that points to array1 of pointers to arrays of pointers that have elements of pointers that points to another arrays of pointers to arrays of integers that consists of integer elements.

Note: Each array consist of three elements.

here is my approach:-

//C99

#include <stdio.h>
#include <stdlib.h>
int main()
{



/* Level 3 */
int arrays_int_3_1_1[3] = {0,1,2};
int arrays_int_3_1_2[3] = {3,4,5};
int arrays_int_3_1_3[3] = {6,7,8};
    
int arrays_int_3_2_1[3] = {9,10,11};
int arrays_int_3_2_2[3] = {12,13,14};
int arrays_int_3_2_3[3] = {15,16,17};

int arrays_int_3_3_1[3] = {18,19,20};
int arrays_int_3_3_2[3] = {21,22,23};
int arrays_int_3_3_3[3] = {24,25,26};


/* Level 2 */
void *arrays_2_1[3] = {(void*)arrays_int_3_1_1,(void*)arrays_int_3_1_2,(void*)arrays_int_3_1_3};
void *arrays_2_2[3] = {(void*)arrays_int_3_2_1,(void*)arrays_int_3_2_2,(void*)arrays_int_3_2_3};
void *arrays_2_3[3] = {(void*)arrays_int_3_3_1,(void*)arrays_int_3_3_2,(void*)arrays_int_3_3_3}; 

/* Level 1*/
void **array1[3] = {arrays_2_1,arrays_2_2,arrays_2_3};

/* Level 0*/
void ***ptr0 = array1;

/*-----------------------------*/

for (int i = 0 ; i <27 ; i++)
{
    // Question here..
    printf("%d \n", <??? How to do the dereference to access each element ???>);
}

}

Quesiton is >> How to do the dereference to access each element

MSamyGawad
  • 71
  • 6
  • 1
    Why are you using void pointer, exactly? – B Remmelzwaal Mar 06 '23 at 20:55
  • You've posted some code, but I don't see a question. – Kevin Mar 06 '23 at 20:56
  • Does this answer your question? [How can i create an n-dimensional array in c](https://stackoverflow.com/questions/19883518/how-can-i-create-an-n-dimensional-array-in-c) – B Remmelzwaal Mar 06 '23 at 20:56
  • 4
    "I want to declare Pointer ptr0 that points to array1 of pointers to arrays of pointers that have elements of pointers that points to another arrays of pointers to arrays of integers that consists of integer elements." My guess is that you do **not** want to do that. That sounds way too confusing for anyone to understand. – Steve Summit Mar 06 '23 at 20:56
  • It is for demonstration purposes, the requirment is to have any type of data at level 3 so I used void* to be able to cast it later – MSamyGawad Mar 06 '23 at 20:56
  • @SteveSummit, I was working around pointers and structs and this issue poped. I wanna build deep understanding for the concept – MSamyGawad Mar 06 '23 at 20:59
  • @Kevin , Yeah it was in the code, I explicitly posed it after the code. Sorry for that – MSamyGawad Mar 06 '23 at 21:00
  • @BRemmelzwaal, I don't think so. it doesn't help – MSamyGawad Mar 06 '23 at 21:02
  • Do you want the actual data to be `int`, or "any type of data"? Very, very different requirement – Steve Summit Mar 06 '23 at 21:04
  • *Level three* could be arrays of any type of data which i have to cast to, later , @SteveSummit – MSamyGawad Mar 06 '23 at 21:07
  • I think I found it `printf("%d \n", (*(((int*)((**ptr0))))+i));` – MSamyGawad Mar 06 '23 at 21:08
  • 1
    @Msamy just wanted to tell you that `printf("%d \n", (*(((int*)((**ptr0))))+i));` is not the correct solution. You are just adding `i` to the first element. Try changing the first element or use `printf("%d \n", (*(((int*)((**ptr0))))+2*i));` to see. – Keyvan Khademi Mar 06 '23 at 21:15
  • 3
    `*(((int*)((**ptr0))))+i` is not a correct solution. It exhibits undefined behavior when `i` exceeds 2 because of overrunning the bounds of `arrays_int_3_1_1`. In practice, the UB might happen to manifest the overall program behavior you are hoping for and expecting, but even if, contrafactually, we assumed that we could safely and reliably examine arbitrary memory belonging to the program by overrunning array bounds like so, there is no guarantee that the nine separate `arrays_int_3_*` are arranged in memory such that doing so obtains the correct results. – John Bollinger Mar 06 '23 at 21:24
  • 1
    @TedLyngmo , Yeah sorry it was my fault. Thanks for informing me about this missleading point . – MSamyGawad Mar 06 '23 at 21:24
  • @KeyvanKhademi , YES, yo are right.. I have just noticed that. Thanks for clarification – MSamyGawad Mar 06 '23 at 21:29
  • 2
    If you insist on having one loop `for(int i = 0; i < 27; i++)` to access the whole array, then you need to be sure that all the subarrays are absolutely contiguous, meaning you'll need to start with `int arrays_int_3[27] = {0, 1, 2, ..., 24, 25, 26};`, not 9 separate arrays. – Steve Summit Mar 06 '23 at 21:34
  • @JohnBollinger, Yes this do happens as arrays are not sorted in memeory one after each another. thanks for clarifing this issue. when i edited the code be like `printf("%d \n", (*(((int*)(**ptr0))+i)));` I do get garbage data after the first 3 element, which i didn't notice at first because the original data was already sorted and i just used this line `printf("%d \n", (*(((int*)((**ptr0))))+i));` to get the first element `0` and increment it as integer (which was miss leading) as @KeyvanKhademi illustrated too – MSamyGawad Mar 06 '23 at 21:36
  • Is there any reason why you are eliminating type information by casting to `void **` instead of `int **`, which is what it is? – Neil Mar 06 '23 at 21:37
  • @SteveSummit, Yes I realized it after ( **KeyvanKhademi** & **and JohnBollinger** ) illustration . Thanks for you considration – MSamyGawad Mar 06 '23 at 21:41
  • 1
    @SteveSummit. Only if the OP insists on accessing each `int` *with a single indexing operation* or equivalent would contiguity be essential. *Using a single loop* does not require or imply that. – John Bollinger Mar 06 '23 at 21:41

2 Answers2

3

ptr0 points to the first element of array1 (array1[0]), and ptr0 can therefore be used as an alias of array1.

The elements of array1 each point to the first element of one of the arrays_2_*, and can therefore be used as aliases for these.

Each element of each of the arrays_2_* is a pointer to the first element of one of the arrays_3_*, cast to type void *. Casting back to type int * will yield an alias for the corresponding arrays_int_3_*.

There is more than one way to perform the dereferencing, but you're probably looking for something along these lines:

    int j = ((int *)ptr0[l][m])[n];
    //              \__a__/
    //              \___b____/
    //      \____________c____/
    //      \_____________d______/

    //  a: one element of array1 (a void **)
    //  b: one element of one of the arrays_2_* (a void *)
    //  c: (b), converted to type int *; this points into one of the arrays_int_3_*
    //  d: one element of one of the arrays_int_3_*

How to convert a single integer i, in the range 0 ... 26, to a triple l, m, n, each in the range 0 ... 2, is left as an exercise.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Insightful answer, however i was looking to accessing *Level 3* elements using one operator `i` I appreciate your help, thank – MSamyGawad Mar 06 '23 at 21:17
  • 1
    Yes, @Msamy, so express `l`, `m`, and `n` as functions of `i`. As I said, I left that as an exercise. I take this overall as an academic assignment because it is absurd for real-world code to do something like this, and I justify doing even as much of your homework as I have done by providing a detailed explanation. – John Bollinger Mar 06 '23 at 21:28
2

Not sure why you are casting them to void* but I cast them back to print them.

#include <stdio.h>
#include <stdlib.h>
int main()
{



/* Level 3 */
int arrays_int_3_1_1[3] = {0,1,2};
int arrays_int_3_1_2[3] = {3,4,5};
int arrays_int_3_1_3[3] = {6,7,8};
    
int arrays_int_3_2_1[3] = {9,10,11};
int arrays_int_3_2_2[3] = {12,13,14};
int arrays_int_3_2_3[3] = {15,16,17};

int arrays_int_3_3_1[3] = {18,19,20};
int arrays_int_3_3_2[3] = {21,22,23};
int arrays_int_3_3_3[3] = {24,25,26};


/* Level 2 */
void *arrays_2_1[3] = {(void*)arrays_int_3_1_1,(void*)arrays_int_3_1_2,(void*)arrays_int_3_1_3};
void *arrays_2_2[3] = {(void*)arrays_int_3_2_1,(void*)arrays_int_3_2_2,(void*)arrays_int_3_2_3};
void *arrays_2_3[3] = {(void*)arrays_int_3_3_1,(void*)arrays_int_3_3_2,(void*)arrays_int_3_3_3}; 

/* Level 1*/
void **array1[3] = {arrays_2_1,arrays_2_2,arrays_2_3};

/* Level 0*/
void ***ptr0 = array1;

/*-----------------------------*/

for (int i = 0 ; i < 27 ; i++)
{
    printf("%d \n", ((int*)(ptr0[i/9])[(i/3)%3])[i%3]);
}

}