Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!usc!zaphod.mps.ohio-state.edu!rpi!batcomputer!christos From: christos@batcomputer.tn.cornell.edu (Christos S. Zoulas) Newsgroups: comp.lang.c Subject: Re: 2D arrays and pointers in ANSI C. (source) Keywords: malloc, arrays, arrayn Message-ID: <1990Dec2.125713.19371@batcomputer.tn.cornell.edu> Date: 2 Dec 90 12:57:13 GMT References: <11616.2757eaf1@ecs.umass.edu> Organization: Electrical Engineering, Cornell University, Ithaca NY Lines: 474 In article <11616.2757eaf1@ecs.umass.edu> lim@ecs.umass.edu writes: >Hi, > >I'd appreciate any answers you may have to the following problem. > It's about 2D arrays and pointers in ANSI C. > ... >I'm aware that it's possible to use just pointers (*) to access the array, but >have had no luck trying to use something like matrix[i][j] in the test_matrix >function. Is it possible to use matrix[i][j] at all? I've had no problem using >matrix[i] for a *matrix argument (1D array). I think the following piece of code will solve your problem: #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'README' <<'END_OF_FILE' X# X# README Fri Sep 8 02:12:57 EDT 1989 X# XThis a a dynamic memory allocator for multi-dimensional arrays. XIt computes the size of the array, (size of data + size of pointers). XThen it allocates the array using malloc, and threads the pointers Xto form a multi-dimensional array. XThe source is in arrayn.c, and with it there are 2 test programs Xsmalltest.c and bigtest.c X X XPlease send comments, bugfixes etc. to X Xchristos@tesla.ee.cornell.edu or Xchristos@crnlee.bitnet END_OF_FILE if test 467 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(320 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# X# Makefile for arrayn X# XSHELL = /bin/sh X#CFLAGS = -g -DDEBUG XCFLAGS = -O X Xall : smalltest bigtest X @echo "All done" X Xsmalltest : arrayn.o smalltest.o X cc ${CFLAGS} arrayn.o smalltest.o -o smalltest X Xbigtest : arrayn.o bigtest.o X cc ${CFLAGS} arrayn.o bigtest.o -o bigtest X Xarrayn.o : arrayn.c X Xclean : X rm -f ${OBJ} END_OF_FILE if test 320 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'arrayn.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'arrayn.c'\" else echo shar: Extracting \"'arrayn.c'\" \(4107 characters\) sed "s/^X//" >'arrayn.c' <<'END_OF_FILE' X/* $Header: /home/hyperion/mu/christos/src/mine/lib/arrayn/RCS/arrayn.c,v 1.2 90/02/26 02:20:42 christos Exp $ */ X/* X * arrayn.c: Dynamic memory allocator for an n - dimensional array. X * X * $Log: arrayn.c,v $ X * Revision 1.2 90/02/26 02:20:42 christos X * ANSI conformance. X * X * Revision 1.1 89/09/08 02:23:03 christos X * Initial revision X * X */ X#ifndef lint Xstatic char rcsid[] = "$Id: arrayn.c,v 1.2 90/02/26 02:20:42 christos Exp $"; X#endif /* lint */ X X#ifdef DEBUG X#include X#endif /* DEBUG */ X X#ifndef __STDC__ X#include Xextern char *malloc(); Xtypedef char genptr_t; X#else X#include Xextern void *malloc(unsigned n); Xtypedef void genptr_t; X#endif X Xtypedef unsigned long u_long; X Xtypedef struct _dimension_t { X u_long size; /* Number of elements in the dimension */ X u_long totalsize; /* Total number of elements */ X u_long elsize; /* Size of a single element in bytes */ X u_long offset; /* offset from beginning of array */ X} dimension_t; X X/* arrayn(): X * Allocate an n-dimensional array. X * We want to allocate only one chunk, so that free X * will free the whole array. X */ X#ifndef __STDC__ Xchar * X/*VARARGS*/ Xarrayn(numdim, va_alist) Xint numdim; /* Number of dimensions */ Xva_dcl X#else Xvoid * Xarrayn(int numdim, ...) X#endif X{ X int i, j; X dimension_t *dim; /* Info about each dimension */ X u_long total_size, /* Total size of the array */ X pointer_size, /* Pointer size of the array */ X element_size; /* Element size of the array */ X genptr_t *array; /* the multi-dimensional array */ X genptr_t **ptr, *data; /* Pointer and data offsets */ X va_list va; /* Current pointer in the argument list */ X X#ifndef __STDC__ X va_start(va); X#else X va_start(va, numdim); X#endif X X if ( (dim = (dimension_t *) X malloc( (unsigned) (numdim * sizeof(dimension_t)))) X == (dimension_t *) 0 ) X return((genptr_t *) 0); X X for ( i = 0; i < numdim; i++ ) { X dim[i].size = va_arg(va, u_long); X dim[i].elsize = sizeof(genptr_t *); X } X dim[numdim-1].elsize = va_arg(va, u_long); X X va_end(va); X X /* X * Compute the size of the array to be allocated X * elements : (x * y * z ... w * elementsize) X * pointers : (x * pointersize + X * y * x * pointersize + X * z * y * x * pointersize .. X */ X dim[0].totalsize = dim[0].size; X dim[0].offset = 0; X for ( i = 1; i < numdim; i++ ) { X dim[i].totalsize = dim[i-1].totalsize * dim[i].size; X dim[i].offset = dim[i-1].offset + dim[i-1].totalsize * dim[i-1].elsize; X } X X element_size = dim[numdim-1].offset + X dim[numdim-1].totalsize * dim[numdim-1].elsize; X pointer_size = dim[numdim-1].totalsize; X X total_size = element_size + pointer_size; X X#ifdef DEBUG X (void) fprintf(stderr, "%20s : %10d\n", "Number of dimensions", X numdim, numdim); X (void) fprintf(stderr, "%20s : %10d (%.8x)\n", "Unit size", X dim[numdim-1].elsize, dim[numdim-1].elsize); X (void) fprintf(stderr, "%20s : %10d (%.8x)\n", "Size of pointers", X pointer_size, pointer_size); X (void) fprintf(stderr, "%20s : %10d (%.8x)\n", "Size of elements", X element_size, element_size); X (void) fprintf(stderr, "%20s : %10d (%.8x)\n", "Total size", X total_size, total_size); X (void) fprintf(stderr, "\nDimension\tSize\tTotal Size\tOffset\tElement\n"); X for ( i = 0; i < numdim; i++ ) X (void) fprintf(stderr, "%9d\t%4d\t%10d\t%6d\t%7d\n", i, dim[i].size, X dim[i].totalsize, dim[i].offset, dim[i].elsize); X#endif /* DEBUG */ X X /* X * Allocate space to hold the array X */ X if ( (array = (genptr_t *) malloc((unsigned) total_size)) == X (genptr_t *) 0 ) { X (void) free((genptr_t *) dim); X return((genptr_t *) 0); X } X X /* X * Thread the pointers X */ X for ( i = 0; i < numdim - 1; i++ ) { X ptr = (genptr_t **) (array + dim[i].offset); X data = (genptr_t *) (array + dim[i+1].offset); X for ( j = 0; j < dim[i].totalsize; j++ ) X ptr[j] = data + j * dim[i+1].elsize * dim[i+1].size; X } X X (void) free((genptr_t *) dim); X return(array); X X} /* end arrayn */ END_OF_FILE if test 4107 -ne `wc -c <'arrayn.c'`; then echo shar: \"'arrayn.c'\" unpacked with wrong size! fi # end of 'arrayn.c' fi if test -f 'bigtest.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'bigtest.c'\" else echo shar: Extracting \"'bigtest.c'\" \(3020 characters\) sed "s/^X//" >'bigtest.c' <<'END_OF_FILE' X/* $Header: /home/hyperion/mu/christos/src/mine/lib/arrayn/RCS/bigtest.c,v 1.1 89/09/08 02:23:05 christos Exp Locker: christos $ */ X/* X * bigtest.c: Test for arrayn. X * X * $Log: bigtest.c,v $ X * Revision 1.1 89/09/08 02:23:05 christos X * Initial revision X * X */ X#ifndef lint Xstatic char rcsid[] = "$Id: bigtest.c,v 1.1 89/09/08 02:23:05 christos Exp Locker: christos $"; X#endif /* lint */ X X#include X Xtypedef struct test_t { X int i, j, k, l, m; X} test_t; X Xextern char *arrayn(); X X#define DIMNUM 5 X#define D_I 12 X#define D_J 23 X#define D_K 51 X#define D_L 4 X#define D_M 3 X Xstatic char *pname; X X/*ARGSUSED*/ Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int i, j, k, l, m; X test_t *****ptr; X X pname = *argv; X X if ((ptr = (test_t *****) X arrayn(DIMNUM, D_I, D_J, D_K, D_L, D_M, sizeof(test_t))) == X (test_t *****) 0 ) { X (void) fprintf(stderr, "%s: Out of memory.\n", pname); X exit(1); X } X X#ifdef DEBUG X for ( i = 0; i < D_I; i++ ) X (void) fprintf(stderr, "ptr[%d] = %.8x(%.8x)\n", X i, &ptr[i], ptr[i]); X X for ( i = 0; i < D_I; i++ ) X for ( j = 0; j < D_J; j++ ) X (void) fprintf(stderr, "ptr[%d][%d] = %.8x(%.8x)\n", X i, j, &ptr[i][j], ptr[i][j]); X X for ( i = 0; i < D_I; i++ ) X for ( j = 0; j < D_J; j++ ) X for ( k = 0; k < D_K; k++ ) X (void) fprintf(stderr, "ptr[%d][%d][%d] = %.8x(%.8x)\n", X i, j, k, &ptr[i][j][k], ptr[i][j][k]); X X for ( i = 0; i < D_I; i++ ) X for ( j = 0; j < D_J; j++ ) X for ( k = 0; k < D_K; k++ ) X for ( l = 0; l < D_L; l++ ) X (void) fprintf(stderr, "ptr[%d][%d][%d][%d] = %.8x(%.8x)\n", X i, j, k, l, &ptr[i][j][k][l], ptr[i][j][k][l]); X X for ( i = 0; i < D_I; i++ ) X for ( j = 0; j < D_J; j++ ) X for ( k = 0; k < D_K; k++ ) X for ( l = 0; l < D_L; l++ ) X for ( m = 0; m < D_M; m++ ) X (void) fprintf(stderr, X "ptr[%d][%d][%d][%d][%d] = %.8x\n", X i, j, k, l, m, ptr[i][j][k][l][m]); X#endif /* DEBUG */ X /* X * Load each element with unique data X */ X for ( i = 0; i < D_I; i++ ) X for ( j = 0; j < D_J; j++ ) X for ( k = 0; k < D_K; k++ ) X for ( l = 0; l < D_L; l++ ) X for ( m = 0; m < D_M; m++ ) { X ptr[i][j][k][l][m].i = i; X ptr[i][j][k][l][m].j = j; X ptr[i][j][k][l][m].k = k; X ptr[i][j][k][l][m].l = l; X ptr[i][j][k][l][m].m = m; X } X X for ( i = 0; i < D_I; i++ ) X for ( j = 0; j < D_J; j++ ) X for ( k = 0; k < D_K; k++ ) X for ( l = 0; l < D_L; l++ ) X for ( m = 0; m < D_M; m++ ) X if ( ptr[i][j][k][l][m].i != i || X ptr[i][j][k][l][m].j != j || X ptr[i][j][k][l][m].k != k || X ptr[i][j][k][l][m].l != l || X ptr[i][j][k][l][m].m != m) { X (void) fprintf(stderr, X "%s: element ptr[%d][%d][%d][%d][%d] bad (%d, %d, %d, %d, %d)\n", X pname, i, j, k, l, m, X ptr[i][j][k][l][m].i, X ptr[i][j][k][l][m].j, X ptr[i][j][k][l][m].k, X ptr[i][j][k][l][m].l, X ptr[i][j][k][l][m].m); X exit(1); X } X (void) fprintf(stderr, "arrayn ok.\n"); X exit(0); X} /* end main */ END_OF_FILE if test 3020 -ne `wc -c <'bigtest.c'`; then echo shar: \"'bigtest.c'\" unpacked with wrong size! fi # end of 'bigtest.c' fi if test -f 'smalltest.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'smalltest.c'\" else echo shar: Extracting \"'smalltest.c'\" \(2175 characters\) sed "s/^X//" >'smalltest.c' <<'END_OF_FILE' X/* $Header: /home/hyperion/mu/christos/src/mine/lib/arrayn/RCS/smalltest.c,v 1.1 89/09/08 02:23:07 christos Exp Locker: christos $ */ X/* X * smalltest.c: Test for arrayn. X * X * $Log: smalltest.c,v $ X * Revision 1.1 89/09/08 02:23:07 christos X * Initial revision X * X */ X#ifndef lint Xstatic char rcsid[] = "$Id: smalltest.c,v 1.1 89/09/08 02:23:07 christos Exp Locker: christos $"; X#endif /* lint */ X X#include X Xtypedef struct test_t { X int i, j, k; X} test_t; X Xextern char *arrayn(); X X#define DIMNUM 3 X#define D_I 4 X#define D_J 5 X#define D_K 6 X Xstatic char *pname; X X/*ARGSUSED*/ Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int i, j, k; X test_t ***ptr; X X pname = *argv; X X if ((ptr = (test_t ***) arrayn(DIMNUM, D_I, D_J, D_K, sizeof(test_t))) == X (test_t ***) 0 ) { X (void) fprintf(stderr, "%s: Out of memory.\n", pname); X exit(1); X } X X#ifdef DEBUG X for ( i = 0; i < D_I; i++ ) X (void) fprintf(stderr, "ptr[%d] = %.8x(%.8x)\n", X i, &ptr[i], ptr[i]); X X for ( i = 0; i < D_I; i++ ) X for ( j = 0; j < D_J; j++ ) X (void) fprintf(stderr, "ptr[%d][%d] = %.8x(%.8x)\n", X i, j, &ptr[i][j], ptr[i][j]); X X for ( i = 0; i < D_I; i++ ) X for ( j = 0; j < D_J; j++ ) X for ( k = 0; k < D_K; k++ ) X (void) fprintf(stderr, "ptr[%d][%d][%d] = %.8x\n", X i, j, k, ptr[i][j][k]); X#endif /* DEBUG */ X X /* X * Load each element with unique data X */ X for ( i = 0; i < D_I; i++ ) X for ( j = 0; j < D_J; j++ ) X for ( k = 0; k < D_K; k++ ) { X ptr[i][j][k].i = i; X ptr[i][j][k].j = j; X ptr[i][j][k].k = k; X } X X for ( i = 0; i < D_I; i++ ) X for ( j = 0; j < D_J; j++ ) X for ( k = 0; k < D_K; k++ ) { X#ifdef DEBUG X (void) fprintf(stderr, X "ptr[%d][%d][%d] = (%d, %d, %d)\n", X i, j, k, ptr[i][j][k].i, ptr[i][j][k].j, X ptr[i][j][k].k); X#endif /* DEBUG */ X X if ( ptr[i][j][k].i != i || ptr[i][j][k].j != j || X ptr[i][j][k].k != k ) { X (void) fprintf(stderr, X "%s: element ptr[%d][%d][%d] bad (%d, %d, %d)\n", X pname, i, j, k, ptr[i][j][k].i, ptr[i][j][k].j, X ptr[i][j][k].k); X exit(1); X } X } X (void) fprintf(stderr, "arrayn ok.\n"); X exit(0); X} /* end main */ END_OF_FILE if test 2175 -ne `wc -c <'smalltest.c'`; then echo shar: \"'smalltest.c'\" unpacked with wrong size! fi # end of 'smalltest.c' fi echo shar: End of shell archive. exit 0 -- /------------------------------------------------------------------------\ | Christos Zoulas | 389 Theory Center, Electrical Engineering, | | christos@ee.cornell.edu | Cornell University, Ithaca NY 14853. | | christos@crnlee | Phone: Disconnected | Fax: (607) 254 4565 | Brought to you by Super Global Mega Corp .com