[comp.lang.c++] parameter

jk@cs.man.ac.uk (John Kewley ICL) (08/02/90)

One of our staff is whingeing about having to specify the size of all
dimensions for a multidimensional array (beyond the first that is).

Can anyone give me some good reasons why this is, so I can placate him.
He claims that it can be done in C so why can't it be done in C++.
--
        J.K.
 
John M. Kewley, ICL, Wenlock Way, West Gorton, Manchester. M12 5DR
Tel:   (+44) 61 223 1301 X2138  Email: jk@r6.cs.man.ac.uk / jk@nw.stl.stc.co.uk

eapu034@orion.oac.uci.edu (Carl F. Edman) (08/04/90)

In article <1545@m1.cs.man.ac.uk> jk@cs.man.ac.uk (John Kewley ICL) writes:
>One of our staff is whingeing about having to specify the size of all
>dimensions for a multidimensional array (beyond the first that is).
>
>Can anyone give me some good reasons why this is, so I can placate him.
>He claims that it can be done in C so why can't it be done in C++.
>--
>        J.K.
> 
For starters: This is in no way possible in C or C++ and couldn't be
as the following example might illustrate.

In one source-file:

char array[4][6][8];

In another source-file:

extern char array[][][];        // Using NO dimensional specifiers
array[3][5][7]='a';

Now, how should the compiler of the second source-file find out where
element a[3][5][7] is in respect to the base-address pointed to by a,
without knowing the dimensions of the array ?
In the example the element would be the (3*6+5)*8+7st (counting from zero)
of the array. As you see the knowing the exact dimensions of the array
is neccessary for the second file to compile thus: No there is no way
to use a declaration like the one above.

	Carl Edman

Theorectial Physicist,N.:A physicist whose   | Send mail
existence is postulated, to make the numbers |  to
balance but who is never actually observed   | cedman@golem.ps.uci.edu
in the laboratory.                           | eapu034@orion.oac.uci.edu

jbuck@galileo.berkeley.edu (Joe Buck) (08/04/90)

jk@cs.man.ac.uk (John Kewley ICL) writes:
> >One of our staff is whingeing about having to specify the size of all
> >dimensions for a multidimensional array (beyond the first that is).
> >Can anyone give me some good reasons why this is, so I can placate him.
> >He claims that it can be done in C so why can't it be done in C++.

eapu034@orion.oac.uci.edu (Carl F. Edman) writes:
> For starters: This is in no way possible in C or C++ and couldn't be
> as the following example might illustrate.
> In one source-file:

> char array[4][6][8];
(rest of example deleted -- you can't do it this way)


Oh, you of little imagination.  Of course it's possible.  You can make an
object that looks just like a 2-D array, and you can pass it around without
worrying about the size.  It can even be a triangular array and use half
the storage.  Here's the trick:

double **mat_alloc (int nrows, int ncols) {
	double **t = new double* [nrows];
	for (int i = 0; i < ncols; i++)
		t[i] = new double [ncols];
}


When John Kewley's friend says "it can be done in C" this is probably what
he means, except that malloc is used instead of new.  The code is a lot
easier to understand when written with new, though.

Voila.  Do the analogous thing for three dimensions.  Now you can use the
object created by this function as a multidimensional array and pass it
around to various functions.

In C++ you can get really fancy and create sparse matrix classes, by
overloading
the [] operator and making separate classes for rows, planes, etc.
--
Joe Buck
jbuck@galileo.berkeley.edu	 {uunet,ucbvax}!galileo.berkeley.edu!jbuck	

steve@taumet.com (Stephen Clamage) (08/04/90)

jk@cs.man.ac.uk (John Kewley ICL) writes:
>One of our staff is whingeing about having to specify the size of all
>dimensions for a multidimensional array (beyond the first that is).
>Can anyone give me some good reasons why this is, so I can placate him.
>He claims that it can be done in C so why can't it be done in C++.

It can't be done in C either, and you should get him to put up or
shut up (that's American for "prove it's true or stop whingeing",
whatever "whingeing" may be).  This is specified in every C text I've
ever seen, including K&R 1, section 5.7.  ANSI C also requires it.

A specific example:  If you declare
	T x[n][m];
it means x is an array of n elements, each of which is an array of
m elements of type T.  When you then say
	j = x[i][j];
the compiler knows that each row contains an array of m elements,
so it multiplies m*sizeof(T) to get the size of each row in the
array, multiplies that by i to get the offset of the row, and then
adds j*sizeof(T) to get the final offset.  If you do not declare the
value of m, how do you find the start of any row beyond the 0th row?
You can't.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

rfg@NCD.COM (Ron Guilmette) (08/04/90)

In article <1545@m1.cs.man.ac.uk> jk@cs.man.ac.uk (John Kewley ICL) writes:
>One of our staff is whineing about having to specify the size of all
>dimensions for a multidimensional array (beyond the first that is).
>
>Can anyone give me some good reasons why this is, so I can placate him.
>He claims that it can be done in C so why can't it be done in C++.

I don't believe that C and C+ are different here.

Consider the following:

	int foobar (int arg1[][5], int (*arg2)[5]);

It ain't obvious, but both arguments have exactly the same type (in both C
and in C++).  That's because of an obscure rule that says that if the type
of a parameter is an array type, that type gets implicitly converted to
a pointer type.

Now if your collegue is grumbling about C vs. C++, tell him to try this
on his favorite C compiler:

	int foobar (p)
		int (*iap)[];
	{
		p++;
	}

When he comes back to you and says that the increment statement was flagged
with an error, then you can both have fun trying to understand why.

-- 
// Ron Guilmette
// C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.

jac@gandalf..llnl.gov (James Crotinger) (08/07/90)

In article <37961@ucbvax.BERKELEY.EDU> jbuck@galileo.berkeley.edu (Joe Buck) writes:
>
>
>double **mat_alloc (int nrows, int ncols) {
>	double **t = new double* [nrows];
>	for (int i = 0; i < ncols; i++)
>		t[i] = new double [ncols];
>}
>
  There are at least a couple of problems with this approach. The
first is that, as written, the inter-row spacing is not constant. This
may hurt your performance on some architectures when you try to do a
loop over the first index. (This is particularly true of vectorizing
architectures but can also give a performance hit on systems with
interleaved memory access).  In fact optimization in general is
greatly hindered by the use of a double ** to represent a simple
square or rectanglar array since the optimizer no longer has any way
of knowing that it is, indeed, dealing with such a simple layout of
the data.

>Joe Buck
>jbuck@galileo.berkeley.edu	 {uunet,ucbvax}!galileo.berkeley.edu!jbuck     


--
=========================================================================
  James A. Crotinger     Lawrence Livermore National Laboratory      //
  jac@gandalf.llnl.gov   P.O. Box 808; L-630                     \\ //
  (415) 422-0259         Livermore CA 94550                       \\/ 

r91400@memqa.uucp (Michael C. Grant) (08/08/90)

In article <65983@lll-winken.LLNL.GOV>, jac@gandalf..llnl.gov (James Crotinger) writes:
> In article <37961@ucbvax.BERKELEY.EDU> jbuck@galileo.berkeley.edu (Joe Buck) writes:
>>
>>
>>double **mat_alloc (int nrows, int ncols) {
>>	double **t = new double* [nrows];
>>	for (int i = 0; i < ncols; i++)
>>		t[i] = new double [ncols];
>>}
>>
>   There are at least a couple of problems with this approach. The
> first is that, as written, the inter-row spacing is not constant. This
> may hurt your performance on some architectures when you try to do a
> loop over the first index. (This is particularly true of vectorizing
> architectures but can also give a performance hit on systems with
> interleaved memory access).  In fact optimization in general is
> greatly hindered by the use of a double ** to represent a simple
> square or rectanglar array since the optimizer no longer has any way
> of knowing that it is, indeed, dealing with such a simple layout of
> the data.

It really depends on how you access the data.  If you are performing
sequential access, then yes I agree that a simple rectangular array
would speed things up quite a bit--but for relatively random access,
you really can't beat this double ** approach.  Some processors 
can implement this as a single indirect addressing with offset instruction.
Most could do it in two instructions.  But, the simple rectangular 
array would require a multiply and addition IN addition to the access.

Of course, if access time is only a small portion of your program's
execution time, then optimizing access won't to diddley to improve
the performance.  For most programs, it's worthless to quibble
over it (see Amdahl's law...)

Michael C. Grant