[comp.lang.fortran] An array by any other name. . .

fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts) (09/16/88)

In article <3630@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>. . . I can't declare an array in C without getting
>one or more pointers declared into the bargain.

Giles, you are not paying attention.  YES YOU CAN.  Please quit
playing semantic games.  C has both ordinary arrays and pointer to
pointer to pointer to . . . arrays.  To paraphrase Giles in a
different argument:

x[i] and x+i are semantically equivalent.  It doesn't matter which way
I say it, they both express a reference to the address of the ith
element from the start of x.  In some cases, x happens to be a
pointer, in others not.

We all enjoy a good argument, but this is getting silly.

Marty
+-+-+-+     I don't know who I am, why should you?     +-+-+-+
   |        fouts@lemming.nas.nasa.gov                    |
   |        ...!ames!orville!fouts                        |
   |        Never attribute to malice what can be         |
+-+-+-+     explained by incompetence.                 +-+-+-+

jlg@lanl.gov (Jim Giles) (09/16/88)

From article <994@amelia.nas.nasa.gov>, by fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts):
> x[i] and x+i are semantically equivalent.  It doesn't matter which way
           ^^^
> I say it, they both express a reference to the address of the ith
> element from the start of x.  In some cases, x happens to be a
> pointer, in others not.

x[i] and *(x+i) are semantically equivalent in C.  I don't _want_ them to 
be.  When I ask for an array, I will always use the first syntax.  When
I ask for a pointer, I will always use the second.  With the pointer,
I _don't_ want the language to apply any constraints on where it can
point; with the array I want array bounds checking - that's two different
semantics folks!!!  I _want_ two different semantics, C doesn't provide
it.  The versions of Fortran which presently have a pointer extension
_do_ give me separate semantics for pointers than for arrays.  I hope the
ANSI Fortran committee _doesn't_ standardize on the C model for introducing
pointers - Cray Fortran already has the kind of pointer extension I want.

Furthermore, in C x[i][j] is _supposed_ to be semantically equivalent
to *(*(x+j)+i).  Statically allocated 2-d arrays aren't implemented
this way!  Many versions of dynamically allocated 2-d arrays are.
In order to get a dynamically allocated to behave semantically like
a statically allocated one I have to use a _different_ declaration
syntax.  

J. Giles

fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts) (09/16/88)

In article <3641@lanl.gov> jlg@lanl.gov (Jim Giles) writes:

> ... - Cray Fortran already has the kind of pointer extension I want.
>

No it doesn't.  The Civic compiler under CTSS supports a fairly
hackneyed dynamic/memory pointer construct.  CFT (at least through CFT
1.15) and CFT77 -- which are "Cray Fortran" -- don't.

(;-)

Marty

+-+-+-+     I don't know who I am, why should you?     +-+-+-+
   |        fouts@lemming.nas.nasa.gov                    |
   |        ...!ames!orville!fouts                        |
   |        Never attribute to malice what can be         |
+-+-+-+     explained by incompetence.                 +-+-+-+

mike@arizona.edu (Mike Coffin) (09/16/88)

From article <3641@lanl.gov>, by jlg@lanl.gov (Jim Giles):
> x[i] and *(x+i) are semantically equivalent in C.  I don't _want_ them to 
> be.  When I ask for an array, I will always use the first syntax.  When
> I ask for a pointer, I will always use the second.

Yes, x[i] and *(x+i) are semantically equivalent.  But nothing says
that x[i] means the same whether x is an array or a pointer (nor that
*(x+i) means the same whether x is an array or a pointer).  There is
nothing wrong with an implementation that generates range-checking
code if x is an array, but doesn't if it is a pointer.  There is
*nothing* hard about doing this: one bit in the symbol table suffices
to differentiate between pointers and arrays.  The fact that most
compilers don't bother is just tradition.

So what you are asking (I guess) is that you would like the syntax ---
brackets vs. * and + --- to be a redundant reminder to the reader that
x is an array or a pointer.  I can't argue with your preference, but
the way it's done does have some advantages.  Chiefly, I guess, the
ability to build data structures that are *not* arrays, but can be
treated like arrays in many ways.  (Whether these are Good Things is
an argument I refuse to get into.)
-- 
Mike Coffin				mike@arizona.edu
Univ. of Ariz. Dept. of Comp. Sci.	{allegra,cmcl2,ihnp4}!arizona!mike
Tucson, AZ  85721			(602)621-2858

jlg@lanl.gov (Jim Giles) (09/16/88)

From article <998@amelia.nas.nasa.gov>, by fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts):
> No it doesn't.  The Civic compiler under CTSS supports a fairly
> hackneyed dynamic/memory pointer construct.  CFT (at least through CFT
> 1.15) and CFT77 -- which are "Cray Fortran" -- don't.

I've used CFT daily for the last 6 years.  I used to be the site support
for the CFT compiler at Los Alamos.  CFT version 1.08 had pointers in it.
I know it did because I had to fix a bug relating to pointers in that
version.  All the versions of CFT since then have had pointers.  The
CFT reference manual claims that pointers were introduced in April 1980.
I have the manual right here on my desk!  I don't know where you got
your information, but mine comes right from the documentation.  (Not
to mention the fact that I use pointers _all_ the time, so I know
there has been no change.)

J. Giles
Los Alamos

ok@quintus.uucp (Richard A. O'Keefe) (09/16/88)

In article <3641@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>Furthermore, in C x[i][j] is _supposed_ to be semantically equivalent
>to *(*(x+j)+i).  Statically allocated 2-d arrays aren't implemented
>this way!  Many versions of dynamically allocated 2-d arrays are.

x[i][j] *is* equivalent to *(*(x+i)+j).
Suppose we have
	double x[20][30];
then	x[i], or equivalently *(x+i) would be of type
	array 30 of double.
This expression is immediately converted to a pointer to its first
element (which thus is of type "pointer to double"), and
	x[i][j] = *(( (double*)& *(x+i) )+j)
I just checked with a UNIX C compiler, and given the declaration above,
x[i][j] and *(*(x+i)+j) yielded the same compiled code.

>In order to get a dynamically allocated to behave semantically like
>a statically allocated one I have to use a _different_ declaration
>syntax.

Nope.	double (*y)[20][30];
	y = (double (*)[20][30]) malloc(sizeof y);
"cdecl" explains this as
	cast malloc(sizeof y) into pointer to array 20 of array 30 of double
Now use it as
	(*y)[i][j]

The only difference is that instead of writing "x" you write "(*y)", and
you do that consistently in the declaration and the uses.

chris@mimsy.UUCP (Chris Torek) (09/16/88)

In article <3641@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>x[i] and *(x+i) are semantically equivalent in C.

(good so far)

>I don't _want_ them to be.

(Well, there is no accounting for taste.)

>...  With the pointer, I _don't_ want the language to apply any
>constraints on where it can point;

None at all?  C requires that it point to some integer.

>with the array I want array bounds checking - that's two different
>semantics folks!!!

Actually not.  You can buy a C compiler (from Sabre) that will
do bounds checking.  (It does the checking on pointers, too,
including on pointers to regions allocated by malloc.)

>Furthermore, in C x[i][j] is _supposed_ to be semantically equivalent
>to *(*(x+j)+i).  Statically allocated 2-d arrays aren't implemented
>this way!

Ah, but they are.

>In order to get a dynamically allocated to behave semantically like
>a statically allocated one I have to use a _different_ declaration
>syntax.  

True, but only with a qualifier.  This applies to dynamically
allocated, dynamically *sized* arrays, which simply do not exist in C.
(Neither do they exist in FORTRAN.)  Also, the C language does not have
`conformant' (dynamically sized, who-cares-how allocated) arrays, which
makes dealing with multidimensional array arguments unnecessarily
painful.  *This* is the only thing FORTRAN has here that C does not.
(It *is* a rather large thing.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

lamaster@ames.arc.nasa.gov (Hugh LaMaster) (09/16/88)

In article <7066@megaron.arizona.edu> mike@arizona.edu (Mike Coffin) writes:
>the way it's done does have some advantages.  Chiefly, I guess, the
>ability to build data structures that are *not* arrays, but can be
>treated like arrays in many ways.  (Whether these are Good Things is
>an argument I refuse to get into.)

I don't refuse.  Indexing pointers through data structures is the path to
perdition.  What happens when you move your code to a word addressable
machine, or a machine with different alignment rules?  If you write code
that uses this unnecessary "advantage", don't complain when you can't port
it.  Some uses of pointers would make the most dyed-in-the-wool Fortran
EQUIVALENCE abuser blush.


-- 
  Hugh LaMaster, m/s 233-9,  UUCP ames!lamaster
  NASA Ames Research Center  ARPA lamaster@ames.arc.nasa.gov
  Moffett Field, CA 94035     
  Phone:  (415)694-6117       

fouts@lemming.nas.nasa.gov.nas.nasa.gov (Marty Fouts) (09/16/88)

In article <14997@ames.arc.nasa.gov> lamaster@ames.arc.nasa.gov.UUCP (Hugh LaMaster) writes:
>
>. . .  Indexing pointers through data structures is the path to
>perdition.  What happens when you move your code to a word addressable
>machine, or a machine with different alignment rules?

My code works just fine when I do this.  It is possible to misuse
pointers, but if you use the model that pointers are pointers to
objects, and do pointer arithmetic rather than integer arithmetic on
your pointers, You don't get alignment or word size dependencies in
pointer code if you do pointer arithmetic.

Pointers can be a semantic problem because they alias multiple names to
the same object and make code more difficult to understand, but even
this can be gotten around by careful use.  (Wirth suggests only using
pointers to point at anonymous objects and coercing pointers to be
able to only point to one type of object.)

Marty
+-+-+-+     I don't know who I am, why should you?     +-+-+-+
   |        fouts@lemming.nas.nasa.gov                    |
   |        ...!ames!orville!fouts                        |
   |        Never attribute to malice what can be         |
+-+-+-+     explained by incompetence.                 +-+-+-+

jlg@lanl.gov (Jim Giles) (09/17/88)

From article <13587@mimsy.UUCP>, by chris@mimsy.UUCP (Chris Torek):
>>...  With the pointer, I _don't_ want the language to apply any
>>constraints on where it can point;
> None at all?  C requires that it point to some integer.
                                                 ^^^^^^^
Actually a nit-pik here: C requires pointers to always point the
an object of the _same_ type as it was declared to be a pointer to.
I like this rule - I will accept it.

>>with the array I want array bounds checking - that's two different
>>semantics folks!!!
> 
> Actually not.  You can buy a C compiler (from Sabre) that will
> do bounds checking.  (It does the checking on pointers, too,
> including on pointers to regions allocated by malloc.)

Ah, but I don't _want_ it to check for pointers.  As long as my pointer
addresses something of the correct type, why should the language care
_where_ it is?  I _want_ the compiler to do bounds checking on arrays
and _not_ pointers.

>>Furthermore, in C x[i][j] is _supposed_ to be semantically equivalent
>>to *(*(x+j)+i).  Statically allocated 2-d arrays aren't implemented
>>this way!
> Ah, but they are.

Ah, but they aren't!  The syntax above _implies_ that there really _is_
a vector of pointers (indexed by j) which point to vectors of values
(indexed by i).  This intermediate vector of pointers is dispensed with
if the compiler can verify that the array was statically declared.  The
most obvious way of declaring a dynamic 2-d array will actually cause
this intermediate vector of pointers to be defined - this is why such
dynamic arrays don't optimize (the pointers in the vector must be assumed
to be possibly aliased).  Defining 2-d dynamic arrays which _don't_ have
this intermediate pointer vector requires more devious declarations (and
usually makes the _use_ of the array syntactically different as well).

> True, but only with a qualifier.  This applies to dynamically
> allocated, dynamically *sized* arrays, which simply do not exist in C.
> (Neither do they exist in FORTRAN.)

Ah, but they _will_ almost certainly exist in the upcomming Fortran.
And I'll be willing to bet that the only difference between such dynamic
arrays and their static counterparts will be a tag on the declaration
and an allocation call.  The use will be identical!

J. Giles
Los Alamos

ok@quintus.uucp (Richard A. O'Keefe) (09/17/88)

In article <3698@lanl.gov> jlg@lanl.gov (Jim Giles) writes:
>From article <13587@mimsy.UUCP>, by chris@mimsy.UUCP (Chris Torek):
>>>Furthermore, in C x[i][j] is _supposed_ to be semantically equivalent
>>>to *(*(x+j)+i).  Statically allocated 2-d arrays aren't implemented
>>>this way!
>> Ah, but they are.
>Ah, but they aren't!
The two notations are in fact identical, not because statically allocated
2-d arrays are full of pointers (they aren't) but because dynamically
allocated ones aren't either.  A previous posting of mine explained how
the equivalence x[i][j] === *(*(x+i)+j) works.  Try it with a compiler!

>>[dynamically allocated arrays in Fortran]
>Ah, but they _will_ almost certainly exist in the upcoming Fortran.
>And I'll be willing to bet that the only difference between such dynamic
>arrays and their static counterparts will be a tag on the declaration
>and an allocation call.  The use will be identical!

	DECLARE P POINTER;
	DECLARE (N INITIAL(20), I, J) BINARY FIXED;
	DECLARE (X, Y, Z) FLOAT;
	DECLARE (
	    LOCAL AUTOMATIC,
	    IMPLICIT_DYNAMIC BASED(P),
	    EXPLICIT_DYNAMIC BASED
	  )(1:N, 1:N) FLOAT;
	...
	X = LOCAL(I, J);
	Y = IMPLICIT_DYNAMIC(I, J);	/* Note no mention of P */
	Z = P->EXPLICIT_DYNAMIC(I, J);	/* Note P-> is required */

Which being translated means "it's been done before".  It is not
immediately clear to me that hiding the pointer P is *always* a good
idea; it really didn't make debugging PL/I code any easier.

PL/I is not a language that springs to mind when one thinks "high
performance".  Was it that people didn't try hard enough, or are there
fast *full* PL/I systems, or is Fortran 8X doomed by the resemblance?