Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site lasspvax.UUCP Path: utzoo!watmath!clyde!cbosgd!cbdkc1!desoto!packard!hoxna!houxm!vax135!cornell!lasspvax!srw From: srw@lasspvax.UUCP (Steve White) Newsgroups: net.lang.c Subject: A BETTER way to do Multidimensional arrays in C Message-ID: <169@lasspvax.UUCP> Date: Sat, 12-Jan-85 23:22:29 EST Article-I.D.: lasspvax.169 Posted: Sat Jan 12 23:22:29 1985 Date-Received: Mon, 14-Jan-85 01:51:50 EST Reply-To: srw@lasspvax.UUCP (Steve White) Organization: Cornell University Dept. of Physics Lines: 108 A few months ago I realized there was a better way to do multidimensional arrays in C. This way is not new; in fact, it is discussed on page 110 of Kernighan and Ritchie. But after reading the discussions in net.lang.c concerning the subject of multidimensional arrays I decided a lot of people might not be aware of it or might not appreciate its advantages. Here's how it works. The following program illustrates the idea (go ahead, try it!): main() { double **array; /* This will be a 10 x 12 array */ int i; array = (double **) calloc(10,sizeof(double *)); /* Number of rows = 10 */ for (i = 0; i < 10; i++) array[i] = (double *) calloc(12,sizeof(double)); /* Number of columns = 12 */ array[2][3] = 3.14159265359; array[4][5] = 2.71828182846; anyfunc(array); } anyfunc(a) double **a; { printf("%.14g %.14g\n",a[2][3],a[4][5]); } We first allocate space for an array of pointers, the length of which is the number of rows. Then each of these pointers is set to point to enough space for one row of the array. Once this is done, then we can pretend we have a regular 2-dimensional array, except that we never have to specify its dimensions to any subroutines that use it. There are a couple of DISADVANTAGES to the above method: 1. It uses slightly more storage. 2. You have to initialize the pointers, as in the above program. It has, however, lots more ADVANTAGES: 1. All storage allocation can be done dynamically. 2. Subroutines don't need to know the dimensions of the array to access its elements. 3. Non-rectangular arrays are as easy as rectangular. 4. The indices do not have to start at zero! Say we wanted our indices to start at 1 instead of 0 in the above program (as in Fortran). Then the initialization would be changed to array = (double **) calloc(10,sizeof(double *)) - 1; for (i = 1; i <= 10; i++) array[i] = (double *) calloc(12,sizeof(double)) - 1; 5. It is FASTER than the standard way (since there is no multiplication needed to calculate the address). To test the relative speeds of this way and the standard way, I ran the following programs: /* Old way */ main() { double array[200][200]; register int i, j, l; for (l = 0; l < 10; l++) for (i = 0; i < 200; i++) for (j = 0; j < 200; j++) array[i][j] = array[j][i]; } /* New way */ main() { double **array; register int i, j, l; array = (double **) calloc(200,sizeof(double *)); for (i = 0; i < 200; i++) array[i] = (double *) calloc(200,sizeof(double)); for (l = 0; l < 10; l++) for (i = 0; i < 200; i++) for (j = 0; j < 200; j++) array[i][j] = array[j][i]; } The "Old way" took 22 sec. on our Vax 11/750, while the "New way" took 17.4 sec. (When the optimizer was invoked with -O, the times were 21.4 and 16.2 sec., for the old and new ways, respectively.) I think this way of handling multidimensional arrays is definitely superior to the standard way, at least where speed and flexibility are important. Hoping this was useful to you (or at least interesting), Steve White Cornell Univ. Dept. of Physics