kd schrieb:

Newbie question here. It's been a while since I've done C programming,

and I hit a wall last night.

Let's say I have a three dimensional array, like so:

int p[2][3][3] =

{{{0,0,0},

{1,1,1},

{0,1,0}},

{{0,1,0},

{1,1,0},

{0,1,0}}};

I also have a number of other three dimensional arrays, generated with

a code generating script. The size of each dimension varies with each

one. Some are [5][3][3], some are [2][5][5], etc...

How would I declare a variable that could hold any of these

3-dimensional arrays? I'm tripping over the pointer syntax.

I'd like to be able to do something like:

int ***val = p; //The variable p from the last example.

I'm pretty sure that ***val is the wrong way to go about it.

It is the wrong way.

int (*val)[3][3] = p;

is the right way to deal with arbitrary amounts of "3 by 3" matrices.

If you want to be able to deal with "arbitrary amounts of arbitrary

row by arbitrary column number matrices", you need three levels of

indirection. For every level but the last you need "index arrays".

Now, there are two ways of representing your "3D array" in memory

which _can_ make things easier:

1) Condensed. I.e. the last column of the first row of the

first matrix is immediately followed by the first column of the

second row of the first matrix and the last column of the last

row of the first matrix is immediately followed by the first

column of the first row of the second matrix.

This means that you could do with one array of int and could

access everything "matrixlike" via

#define INDEX(i, j, k, num_j, num_k) \

(((i) * (max_j) + (j)) * (max_k) + (k))

and

int *array = malloc(sizeof p);

if (NULL == array) {

/* error handling and abort */

}

memcpy(array, p, sizeof p);

for (mat = 0; mat < num_mat; ++mat)

for (row = 0; row < num_row; ++row)

for (col = 0; col < num_col; ++col) {

do_something(array[INDEX(mat,row,col, num_row,num_col)]);

}

If you really insist on

int ***val;

you need the following steps:

num_mat = sizeof p/sizeof p[0];

val = malloc(num_mat * sizeof *val);

if (NULL == val) {

/* error handling and abort */

}

num_row = sizeof p[0] / sizeof p[0][0];

*val = malloc(num_mat*num_row * sizeof **val);

if (NULL == *val) {

/* error handling and abort */

}

for (mat = 1; mat < num_mat; ++mat) {

val[mat] = val[0] + mat*num_row;

}

/* 1 */

for (mat = 0; mat < num_mat; ++mat)

for (row = 0; row < num_row; ++row)

val[mat][row] = p[mat][row];

/* 2 */

in order to use

for (mat = 0; mat < num_mat; ++mat)

for (row = 0; row < num_row; ++row)

for (col = 0; col < num_col; ++col) {

do_something(val[mat][row][col]);

}

Note that this operates on the original array p.

If you want to have val as a "copy of p", you have to replace

/* 1 */ to /* 2 */ by

num_col = sizeof p[0][0] / sizeof p[0][0][0];

**val = malloc(num_mat*num_row*num_col * sizeof ***val); /*3*/

if (NULL == **val) {

/* error handling and abort */

}

memcpy(val, p, sizeof p);

for (mat = 0; mat < num_mat; ++mat)

for (row = 0; row < num_row; ++row)

val[mat][row] = val[0][0] + (mat*num_row + row)*num_col;

2) Maximum array: Say you know that the largest possible array

dimensions are MAX_MAT, MAX_ROW, MAX_COL and

MAX_MAT*MAX_ROW*MAX_COL is not too large. Then declare your

"intermediate" matrix as

int val[MAX_MAT][MAX_ROW][MAX_COL];

and copy the values:

for (mat = 0; mat < num_mat; ++mat)

for (row = 0; row < num_row; ++row)

for (col = 0; col < num_col; ++col) {

val[mat][row][col] = p[mat][row][col];

}

Merits: 1) makes it possible to just memcpy() the array but

can mean resizing of "array" or "**val", "*val", and "val",

respectively. 2) means no resizing but potentially increased

cost for copying -- and much memory consumption.

If you allocate each row separately instead of at once (/*3*/),

you can "resize" the matrix in an easier manner but have

more allocations to take care of.

It depends on your application whether 1) or 2) or a mixed

form or something completely different is best for your...

Cheers

Michael

--

E-Mail: Mine is an /at/ gmx /dot/ de address.