Path: utzoo!attcan!uunet!cs.utexas.edu!sun-barr!rutgers!netnews.upenn.edu!msuinfo!news From: fox@DASHER.NSCL.MSU.EDU Newsgroups: comp.lang.fortran Subject: Re: Dimensioning arrays at run-time, best way? Message-ID: <1990Sep19.122257.3659@msuinfo.cl.msu.edu> Date: 19 Sep 90 12:02:51 GMT Sender: news@msuinfo.cl.msu.edu Organization: National Superconducting Cyclotron Lab Lines: 138 In article , khb@chiba.Eng.Sun.COM (Keith Bierman - SPD Advanced Languages) writes... > >In article <1990Sep18.115704.20642@msuinfo.cl.msu.edu> fox@DASHER.NSCL.MSU.EDU writes: > > In article <1990Sep17.150155.10220@alchemy.chem.utoronto.ca>, mroussel@alchemy.chem.utoronto.ca (Marc Roussel) writes... > > > > >Let your PROGRAM block be a dummy. (I.E. don't put any code into it > >that does anything but set N (the array size) and calls a subroutine > >which does the real work.) Then call your subroutine. Most FORTRAN > >compilers don't check for the right number of parameters in a subroutine > >call, so the following may not be portable, but it should do the work on > >most computers. > >I have often done well the "other way around" instead of > > > > > PROGRAM EXAMPLE > > read(*,*)n > > call sub1(n) > > END > > > > SUBROUTINE SUB1(N,X) > > real X(N) >...... > > END > > > program example > > print*,"how many bytes ?" > read(*,*) nbytes > x=malloc(nbytes) > call realprog(x,nbytes/4) > end > subroutine realprog(x,n) >c >c this is where the "real program" begins >c > real x(n) > >c do processing, including all calls >c > return > end > >The "spelling" of how to procure the memory varies, malloc works on >Sun and most unix boxes; I forget which sys$ call does the trick on >VMS, and etc. but it is usually easy to find. Only a few lines in the >formal main program need to adjusted from system to system. > On the VMS boxes the call is LIB$GET_VM. But, and here's a big but. Most machines this should not work, for the following reasons: 1. In the call to malloc, almost all C library malloc's expect a pass by value for the sizeof the storage region to allocate. Many, but not all FORTRAN's pass constants, and scalars by reference. So rather than malloc allocating the the number of bytes you want, it'll allocate the number of bytes corresponding to the address of the variable nbytes. May be very very big, or very very small. 2. The call of realprog, assumes that passing a scaler which contains a pointer to a subroutine is equivalent to passing an array. This is not usually true. Although the standard does not mandate how subroutines and functions pass arguments between each other, most (not all) compiler pass scalars and arrays by reference, and pass characters in some funny way to allow the size allocated for the character string to be passed along with the pointer to the storage. Forgetting the character string case, in VAX/VMS for example, The call to realprog produces the following argument list (AP) ---> +-------------+ | 2 | (Number of arguments) +-------------+ |ptr to x |----> x ----> malloc'd storage +-------------+ |Ptr to nbytes/4|---> Nbytes/4 temporary variable +-------------+ This is not atypical. This is because FORTRAN mandates that changes to dummy parameters made by a function/subroutine be reflected by changes to the actual parameters, and pointer passing seems the most efficient way to get that job done. What you really want to happen in the call to malloc (using again the VMS argument list format) is to get an argument list that looks like: (AP)----------->+----------------+ | 1| +----------------+ | nbytes | +----------------+ And in the call to realprog: (AP)----------->+-------------------+ | 2 | +-------------------+ | x | +-------------------+ |Ptr to nbytes/4 |------------> Nbytes/4 temporary +-------------------+ In VAX/VMS FORTRAN and in HP-UX FORTRAN, there's an extension which allows the programmer to specify a nonstandard call sequence inline. To do the malloc in VAX/VMS or HP-UX you'd have to: x = malloc(%VAL(nbytes)) And the call to realprog should look like: CALL realprog(%VAL(x), nbytes/4) Passing x by value is the same as passing the region by reference (pointer). In SUN fortran there is also a %VAL exension which must be used when passing scalar parameters to C library functions. In addition, since SUN FORTRAN sticks an underscore in front of function/subroutine names, it is necessary tell the compiler that a function is C using the C pragma, so at the top you'd need to say: EXTERNAL malloc !$pragman C(malloc) Dynamic allocation of storage is something only for the brave and for those well versed in parameter passing mechanisms on the implementation. It's not something that FORTRAN readily supports. Ron Ron Fox | FOX@MSUNSCL.BITNET | Where the name NSCL | FOX@CYCVAX.NSCL.MSU.EDU | goes on before Michigan State University | MSUHEP::CYCVAX::FOX | the quality East Lansing, MI 48824-1321 | | goes in. USA