[net.unix-wizards] Why C is not much better than Pascal at times

gwyn@Brl@sri-unix (09/17/82)

From:     Doug Gwyn <gwyn@Brl>
Date:     14 Sep 82 0:07:02-EDT (Tue)
One of BWK's complaints about Pascal was that the size of an array is
part of its type, so one cannot write reasonable library routines to
deal with variable-length arrays (such as char strings).  Much as I
like C, it suffers from a similar problem:

double norm( n, matrix )	/* returns norm of n x n matrix */
	int	n;
	double	matrix[n][n];	/* ILLEGAL! */
	{
 ...

(Note that the first subscript might as well be 1, due to row major order.)

Since there is no ambiguity about what is meant here, and in fact no way
to pass an actual array of data as an actual parameter, one would expect
the compiler to generate reasonable code within the function body.  What
actually happens, on all C compilers I have tried so far, is that the
compiler claims that ONLY CONSTANT subscripts can be used in the formal
array declaration!

I suppose that the compiler is written so that sizes have to be constants
even in cases where variables make sense.  I urge that consideration be
given to removing this restriction at least for formal array parameters,
since routines like this are obviously useful and currently difficult
to code cleanly.

swatt (09/18/82)

Regarding:

	double norm (n, matrix)
	double matrix[n][n];	/* ILLEGAL */
	{
		...
	}

This is true, and yes, it is a pain.  HOWEVER since by C rules
on pointer arithmatic, the expression:

	foobar[expr]

where ``foobar'' is an array of any scalar type, is in all cases
equivalent to:

	*(foobar + (expr))

If ``foobar'' is a 2-dimensional array of dimension (range1, range2)
of any scalar type,

	foobar[expr1][expr2]

is in all cases equivalent to:

	*(foobar + (range2 * expr1) + expr2)

The effect you want can be gotten by:

	#define MATRIX(X,Y) matrix[((X)*n) + (Y)]
	double norm (n, matrix)
	register n;
	register double *matrix;  /* It's REALLY a pointer; don't
				   * believe the manuals on
				   * "matrix[]" as function arguments!
				   */
	{
		int i,j;
		double z;

		z = MATRIX(i, j);

It's not as convenient, but it does work and I doubt you lose much
in efficiency over what a Pascal or Fortran compiler could do for
you.

In fact, if you declare two-dimensional arrays like:

	double norm (array)
	double array[][40];
	{

The compiler now has enough information to generate code for
doubly-subscripted expressions directly.  In N-dimensional arrays, the
compiler needs to know the range of the outtermost subscripts.

	- Alan S. Watt