To work on 3D arrays with unknown sizes at compile time, I wrote the following program that works :
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int x,y,z;
} dim3D_t;
void print_array(dim3D_t *dim3D, int (*my_array)[dim3D->y][dim3D->z]) {
for (int i_x=0; i_x<dim3D->x; i_x++)
for (int i_y=0; i_y<dim3D->y; i_y++)
for (int i_z=0; i_z<dim3D->z; i_z++)
printf("%d %d %d : %d\n",i_x,i_y,i_z,my_array[i_x][i_y][i_z]);
}
void alloc_and_init_array(dim3D_t *dim3D, int (**my_array)[dim3D->y][dim3D->z]) {
*my_array = malloc( sizeof(int) * dim3D->x * dim3D->y * dim3D->z );
for (int i_x=0; i_x<dim3D->x; i_x++)
for (int i_y=0; i_y<dim3D->y; i_y++)
for (int i_z=0; i_z<dim3D->z; i_z++)
(*my_array)[i_x][i_y][i_z]=100*i_x+10*i_y+i_z;
}
int main() {
dim3D_t dim3D;
int (*my_array)[dim3D.y][dim3D.z];
scanf("%d %d %d", &dim3D.x, &dim3D.y, &dim3D.z);
alloc_and_init_array(&dim3D, &my_array);
print_array(&dim3D, my_array);
}
I found very convenient to access the array elements with syntax like my_array[][][] and only one memory chunk is allocated.
But, now, I would like to have the array as a member in the structure. How can I do that ?
I would like to avoid 1D array (i.e. to add int *array in the structure member and to access to elements using my_struct.my_array[i_x*dim3D.y*dim3D.z+i_y*din3D.z+i_z]) or to have many memory chunk (arrays of int **, int *).
Edit 1 (answer in fact)
Following the Lundin answer and the good idea of the "cast" trick, I wrote a program that do not use FAM. So, I could have more than one array in my structure. It is very convenient. There is only line to add at the beginning of the functions.
This is the code
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int x,y,z;
int *array;
} dim3D_t;
void print_array(dim3D_t *dim3D) {
int (*cast_dim3Darray)[dim3D->y][dim3D->z] = (int(*)[dim3D->y][dim3D->z]) dim3D->array; //cast
for (int i_x=0; i_x<dim3D->x; i_x++)
for (int i_y=0; i_y<dim3D->y; i_y++)
for (int i_z=0; i_z<dim3D->z; i_z++)
printf("%d %d %d : %d\n",i_x,i_y,i_z,cast_dim3Darray[i_x][i_y][i_z]);
}
void alloc_and_init_array(dim3D_t *dim3D) {
dim3D->array = malloc( sizeof(int) * dim3D->x * dim3D->y * dim3D->z );
int (*cast_dim3Darray)[dim3D->y][dim3D->z] = (int(*)[dim3D->y][dim3D->z]) dim3D->array; //cast
for (int i_x=0; i_x<dim3D->x; i_x++)
for (int i_y=0; i_y<dim3D->y; i_y++)
for (int i_z=0; i_z<dim3D->z; i_z++)
cast_dim3Darray[i_x][i_y][i_z]=100*i_x+10*i_y+i_z;
}
int main() {
dim3D_t dim3D;
scanf("%d %d %d", &dim3D.x, &dim3D.y, &dim3D.z);
alloc_and_init_array(&dim3D);
print_array(&dim3D);
}
Flexible array members only work with one single dimension. However, it is safe to cast to/from them to array pointers since what matters for C's type system is that the variables are accessed through an lvalue of type
int. It's a bit cumbersome to work with flexible array members here, since you need to cast. But quite possible.Modified program with a bit of explanation in comments:
Input:
Output: