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