0

I am trying to get a pointer to an array integers to be temporarily remapped in a function later on to save myself pointer math. I've tried to see if any other questions answered it, but I've been unable to reproduce the methods described here, here, and here.

Fundamentally, I just want to temporally treat an integer group and a 3D array to be sure that I don't mess up the pointer math. (I'm looking at this currently because the previous code had made inconsistent assignments to the memory).

#include <stdlib.h>
#define GROUPCOUNT 16
#define SENSORCOUNT 6
#define SENSORDIM   3
int main()
{
int *groupdata = (int *)calloc(GROUPCOUNT * SENSORCOUNT * SENSORDIM,sizeof(int));
int sensordata[SENSORCOUNT*SENSORDIM];
sensordata[7] = 42;  //assign some data 
int (*group3d)[GROUPCOUNT][SENSORCOUNT][SENSORDIM] = groupdata; //<---Here is the problem
group3d[1][5][1] = sensordata[7];  //I want to do this
free(groupdata);
}

In the example above, I want to handle groupdata as group3d temporarily for assignments, and I just cannot seem to wrap myself around the casting. I currently have macros that do the pointer math to enforce the correct structure, but if it was all just in the code, it would be even better when I pass it off. Any suggestions would be greatly appreciated.

note: The 3D cast is to be used in a function way in the bowels of the program. The example is just a minimally viable program for me to try to sort out the code.

b degnan
  • 672
  • 1
  • 14
  • 31
  • What exactly is the error ? Try using the caste. Why do you create a 3 dimensional array dynamically ? instead allocating memory to an `int *` ? – Mazhar Mar 14 '19 at 15:43
  • @Mazhar The array is allocated a `int *` but is passed around, and a function way in the depths would be served by a 3D cast. The error, which makes sense, is `main.c:11:7: warning: incompatible pointer types initializing 'int (*)[16][6][3]' with an expression of type 'int *'` – b degnan Mar 14 '19 at 15:52
  • Yes, this is what's expected. You are assigning an `int (*)[16][6][3]` a simple `int *`. Or more specifically, `group3d` has type `int (*)[16][6][3]` while `groupdata` has type `int *`. So you can't assign that directly. Though you can use the cast. In your case, if you allocate `group3d` directly as 3D array, you still can pass this single pointer to other functions just like you were passing the `groupdata` but this time you won't have to worry about the dimensions. Moreover, `group3d` is a single pointer with size of regular pointer. It is not any 3d array of pointers. – Mazhar Mar 14 '19 at 16:10

3 Answers3

1

When group3d is defined with int (*group3d)[GROUPCOUNT][SENSORCOUNT][SENSORDIM], then *group3d is a three-dimensional array. That would let you use it with (*group3d)[1][5][1].

To use it with group3d[1][5][1], you need group3d to be a pointer to a two-dimensional array:

int (*group3d)[SENSORCOUNT][SENSORDIM] = (int (*)[SENSORCOUNT][SENSORDIM]) groupdata;

(There are some technical concerns about C semantics in aliasing an array of int as an array of array of array of int, but this is not a problem in common compilers with default settings. However, it would be preferable to always use the memory as an array of array of array of int, not as an array of int.)

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • From your comments, it's probably better to just use my macros to do the pointer math then? I was assuming that the compiler would be more reliable doing the mathematics. – b degnan Mar 14 '19 at 16:16
1
  int l = 5, w = 10, h = 15;
  int Data = 45;
  int *k = malloc(l * w * h * sizeof *k);
  // not use this k[a][b][c] = Data;
  //use this is right
   k[a*l*w + b*l + c] = Data;
0

In the example above, I want to handle groupdata as group3d temporarily for assignments, and I just cannot seem to wrap myself around the casting.

One possible solution is to create a multidimensional array dynamically like this. This way you won't have to cast things or worry about the dimensions.

int (*group3d)[GROUPCOUNT][SENSORCOUNT][SENSORDIM] = calloc(1, sizeof(int [GROUPCOUNT][SENSORCOUNT][SENSORDIM]));

(*group3d)[1][5][1] = sensordata[7];  //I want to do this

/* Then you can print it like */
printf("%d\r\n", (*group3d)[1][5][1]);
Mazhar
  • 575
  • 5
  • 20
  • This will fail horribly—there will be no error message but `*group3d[1][5][1]` will access the wrong memory; it should be `(*group3d)[1][5][1]`. And it is not what the question requests; the question requests that access to an element be in the form `group3d[1][5][1]`, not `*group3d[1][5][1]` or `(*group3d)[1][5][1]`. – Eric Postpischil Mar 14 '19 at 16:20
  • Thanks for pointing out the problem. Though I have checked that it is wokring. – Mazhar Mar 14 '19 at 16:24