dynamic array parameters

David Tribble tribble_acn%uta.csnet at csnet-relay.arpa
Mon Dec 23 20:13:07 AEST 1985


Recently a question arose on the net about the problem of passing a multi-
dimensional array, with varying (or `dynamic') dimension bounds, to a
function.  (This is especially useful when dealing with dynamically
allocated arrays.)  This is one way to do it-

#define D1	3		/* array bounds		*/
#define D2	5
#define D3	9

int	a[D1][D2];		/* 2-D array of int	*/

... fnc(a, D1, D2) ...		/* call fnc, passes address of a */

fnc(a, d1, d2)
    int		*a;		/* pointer to int	*/
    int		d1, d2;		/* dimension bounds	*/
{
    int		i, j;

    ... (*(a + i*d1 + j)) ...	/* same as a[i][j]	*/
}

Or, to make things a little easier-

#define index(a,i,j)	(*(a + i*d1 + j))

    ... index(a, i, j) ...	/* same as a[i][j]	*/

Thus for more dimensions-

int	a[D3][D2][D1];		/* 3-D array of int	*/

... fnc(a, D1, D2, D3) ...	/* passes address of a	*/

#define index3(a,i,j,k)	(*(a + (i*d2 + j)*d1 + k))
fnc(a, d1, d2, d3)
    int		*a;		/* array int pointer	*/
    int		d1, d2, d3;	/* dimension bounds	*/
{
    int		i, j, k;

    ... index3(a, i, j, k) ...	/* same as a[i][j][k]	*/
}

Other indexing macros would be-
#define index1(a,i)		(*(a + i))
#define index2(a,i,j)		(*(a + i*d1 + j))
#define index3(a,i,j,k)		(*(a + (i*d2 + j)*d1 + k))
#define index4(a,i,j,k,l)	(*(a + ((i*d3 + j)*d2 + k)*d1 + l))
#define index5(a,i,j,k,l,m)	(*(a + (((i*d4 + j)*d3 + k)*d2 + l)*d1 + m))
Etc.

What you are doing is passing the address of the first element
of the array (int * a) and calculating the address of the array
element you want.  This is exactly what the compiler would
do if it knew the dimensions of the array.  (Because it is just
a pointer, the compiler does not know any dimensions to associate with
it.)

This has the interesting side effect that you can pass (for example)
a 5-dimensional array and treat it as (for example) a 3-dimensional
array.  This is because the parameter is declared as a 1-dimensional
array, and you are manually calculating the offset.

See Harbison & Steele section 5.5, "Array Types", especially section 5.5.2,
"Multidimensional Arrays".  This is also discussed in the white book.

/* run this program to see how it works */

#define D1              3
#define D2              4
#define D3              5

#define index3(a,i,j,k) (*(a + (i*D2 + j)*D1 + k))

main()
{
    int         a[D3][D2][D1];
    int         i, j, k, l;

    for (i = 0; i < D3; ++i) {
        for (j = 0; j < D2; ++j) {
            for (k = 0; k < D1; ++k) {
                a[i][j][k] = i*100 + j*10 + k;
            }
        }
    }
    fnc(a, D3, D2, D1);
}

fnc(a, dim3, dim2, dim1)
int	* a;
int	dim3, dim2, dim1;
{
    int		i, j, k;

    for (i = 0; i < dim3; ++i) {
        for (j = 0; j < dim2; ++j) {
            for (k = 0; k < dim1; ++k) {
                printf("a[%d][%d][%d] = %03d\n",
                    i, j, k, index3(a, i, j, k));
            }
        }
    }
}

Hope this helps.



More information about the Comp.lang.c mailing list