Xref: utzoo comp.lang.fortran:787 comp.lang.c:10828 Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!bloom-beacon!mit-eddie!uw-beaver!cornell!batcomputer!itsgw!steinmetz!uunet!mcvax!philmds!leo From: leo@philmds.UUCP (Leo de Wit) Newsgroups: comp.lang.fortran,comp.lang.c Subject: Re: Variable dimensioning in fortran Keywords: language conversions, FORTRAN, c Message-ID: <517@philmds.UUCP> Date: 21 Jun 88 14:12:57 GMT References: <2742@utastro.UUCP> <20008@beta.UUCP> <224@raunvis.UUCP> <3415@ut-emx.UUCP> <5917@aw.sei.cmu.edu> <29605@cca.CCA.COM> Reply-To: leo@philmds.UUCP (L.J.M. de Wit) Organization: Philips I&E DTS Eindhoven Lines: 134 Sorry this one's so long, I got a bit carried away 8-): --- ------- In article <29605@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes: >In article <5917@aw.sei.cmu.edu> firth@bd.sei.cmu.edu.UUCP (Robert Firth) writes: >>> double **Create2DArray(w,h) >>> int w,h;{ double **r; >>> for(r=(double**)calloc(h,sizeof(*r));h-->0;r[h]=(double*)calloc(w,sizeof(**r))); >>> return(r);} > >>Any Fortran programmer who seriously proposes to convert to C would, in >>my opinion, be advised to study this example very carefully. Verbum >>sapienta sufficit. > > This little trick is all very well, but it does not reproduce the >fortran facility for variable dimensioning, and it does matter. The above >yields an array of arrays. Consider the following: The above C code is not adequate for handling flat arrays; the 2 * 5 elements should be allocated as one chunk, with the r[0], r[1], ... pointing into it, as I explained in a previous article. I'll repeat that code here for clearness (and removed the errors; this one will work 8-): double **Create2DArray(w,h) int w,h; { double **r, *a; a = (double *)calloc(w * h, sizeof(double)); r = (double **)calloc(h,sizeof(double *)); for ( ; --h >= 0; r[h] = a + w * h) ; return r; } This approach has, besides the array being contiguous, as a benifit that only two allocations are needed. The array can be handled both by vectoring: r[0], r[1], ... and by using the flat array pointed to by r[0]. Now for your example: > real a(2,5) > call foo(a) > .... > subroutine foo(a) > real a(10) > ... > >In this example a is originally allocated as an array of 10 contiguous >locations; subroutine foo takes advantage of that knowledge. The point >of fortran subscripting rules is that the dimension structure can be >changed dynamically. And so for C subscripting rules. Watch me: extern double **Create2DArray(); static void foo1(), foo2(), foo3(), fooall(); main() { double **a = Create2DArray(2,5); int i; foo1(a[0]); foo2(a[0]); foo3(a[0]); fooall(a[0]); for (i = 0; i < 10; i++) { printf("%d: %f\n",i,a[0][i]); } } static void foo1(a) /* now using it as a 1 dim array : a[10] */ double *a; { a[7] = 3.0; } static void foo2(a) /* now using it as a 2 dim array : a[2][5] */ double (*a)[5]; { a[1][3] = 45.3; } static void foo3(a) /* now using it as a 3 dim array : a[2][2][2] */ double (*a)[2][2]; { a[1][1][0] = 2.0; } static void fooall(a) /* Full Organ: C major: the previous altogether */ double *a; { double *a1 = a; /* just for symmetry */ double (*a2)[5] = (double (*)[5])a; double (*a3)[2][2] = (double (*)[2][2])a; a1[7] = 3.0; a2[1][3] = 45.3; a3[1][1][0] = 2.0; } Like to see you do the last trick in Fortran! Note that it is both elegant and efficient (although a Fortran programmer will have trouble reading the declarations, the rest of the code is straightforward); the same array can be accessed with whatever dimension you like. The only trouble is that even experienced C programmers often don't know this stuff, mostly because they didn't need it. If you would also like to have the vectors available, pass a itself as parameter, and use a[0], a[1] for vectors; for example, the header of fooall() would then be: static void fooall(a) /* Full Organ: C major: the previous altogether */ double **a; { double *a1 = a[0]; /* just for symmetry */ double (*a2)[5] = (double (*)[5])a[0]; double (*a3)[2][2] = (double (*)[2][2])a[0]; If you don't need the vectors (and probably you won't, seeing the above), Create2DArray could be further simplified; the r[h] vectors are left out and Create2DArray reduces to a macro: #define Create2DArray(w,h) (double **)calloc((w)*(h),sizeof(double)) and then, why not, to avoid difficult declarations: #define Declare1DAcast(a1,a) double *a1 = (a) #define Declare2DAcast(a2,a,m) double (*a2)[(m)] = (double (*)[(m)])(a) #define Declare3DAcast(a3,a,m,n) double (*a3)[(m)][(n)] = \ (double (*)[(m)][(n)])(a) etc. Enjoy! Leo. (C me, feel me, touch me, heel me).