Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!husc6!bloom-beacon!gatech!rutgers!sri-spam!ames!ucbcad!ucbvax!olsen.UUCP!nagler From: nagler@olsen.UUCP (Robert Nagler) Newsgroups: comp.lang.modula2 Subject: Re: Pointers and whatnot Message-ID: <8708241036.AA24504@klaus.olsen.uucp> Date: Mon, 24-Aug-87 11:09:59 EDT Article-I.D.: klaus.8708241036.AA24504 Posted: Mon Aug 24 11:09:59 1987 Date-Received: Tue, 25-Aug-87 02:55:38 EDT Sender: daemon@ucbvax.BERKELEY.EDU Organization: The ARPA Internet Lines: 87 >In that above case, Text is 80 chars, but suppose the length of Text varies. >How would I be able to change the type? >Or suppose I just want 137 bytes of storage of no particular type, can one >have just a POINTER with no TO? According to my compiler, no (Logitech >Modula-2/86). Sorry, there are no dynamic arrays in Modula-2. This is a fundamental problem with the language. I have seen that the BSI language committee has been talking about a new type of "String", but this is not a general solution to supporting dynamically defined bounds for array types. There are several ways around your problem: 1) Use another language which supports real dynamic arrays. 2) Go for the C-style management of arrays as POINTER TO CHAR and increment the pointer yourself to get the desired value. 3) Declare BigArray = POINTER TO ARRAY [ 0 .. MAX( CARDINAL ) ] OF CHAR. When you want to use a variable of that type, you just partially allocate the array, e.g. ALLOCATE( p, theAmountIWant ). However, you must be careful to do your own range checking. 4) Allocate an array which is "big enough", but just remember that "big enough" is never "big enough"! After using M2 for several years, I find approach (3) is the best when coupled with an opaque interface. Here is an example: DEFINITION MODULE Vectors; TYPE Object; PROCEDURE Create( vector : Object; length : CARDINAL ); PROCEDURE Destroy( vector : Object ); PROCEDURE Get( vector : Object; index : CARDINAL ) : REAL; PROCEDURE Set( vector : Object; index : CARDINAL; newValue : REAL ); END Vectors. The implementation of this module does type checking, thus if an index is out of bounds, the program crashes (just as if it were caught by the run-time system). Here is what a Vectors.Object looks like: IMPLEMENTATION MODULE Vectors; CONST (* The following line is system dependent *) maxHigh = ( SysTypes.MAXCARDINAL DIV SysTypes.bitsPerREAL * SysTypes.bitsPerBYTE ) - 2; TYPE Object = POINTER TO ObjectRec; ObjectRec = RECORD high : CARDINAL; data : POINTER TO ARRAY [ 0 .. maxHigh ] OF REAL; END; The implementation of Get looks like: WITH vector^ DO IF index > high THEN ProgErrs.Terminate( "Vectors: range error" ); END; RETURN data^[ index ]; END; (* WITH *) The only problems you have is in being careful that the allocation of "data" is done correctly. It has been our experience that naive users will often make mistakes implementing such modules. However, once implemented, the module provides a very clean interface to dynamic length objects (whatever they may be, in this case, Vectors of REALs). There are a couple of points here. First, we have a fairly advanced debugging environment which includes an "object allocator". We don't usually have problems catching improperly allocated memory areas. Second, this method is not a panacea, that is, the general "string" problem will only be solved with a language modification (I believe). Strings are so critical to most programs that we did not implement an object oriented Strings interface. Instead, we have chosen solution (4) in combination with some much higher level functions which do use dynamic allocation of strings. Applications like Vectors turn out to be faster than just plain ol' arrays when accompanied by higher level functions, e.g. ComputeFx, Multiply, Add, Subtract, ... We have even found a significant speedup after introducing this type of abstraction (as one would expect!). Rob