LETTERS

Revisiting Variably Dimensioned Arrays in C

Dear DDJ,

Many scientific and engineering programmers are changing from Fortran to C or C++ for technical and numerical applications. As with Fortran, C/C++ enable separate development of general-purpose routines, and libraries for holding them, that can be linked later with a variety of programs.

However, a serious weakness of C/C++ is the inability of either language to handle arrays with two or more dimensions as arguments to a function--if the array sizes are to be specified at run time.

With single-dimensioned arrays, there is no problem. In C or C++, the array dimension can be omitted in the function (for example, float a[];). With arrays of two or more dimensions, all sizes except the first must be known at compile time, as these sizes are used by the compiler in generating the machine instructions to access the array elements.

This has been a major cause for the slowness of scientists, mathematicians, and engineers to accept C or C++ as a viable language for their work, despite the availability of better data and program structuring features and recursion.

In his article, "Variably Dimensioned Arrays in C" (DDJ, August 1993), John Ross discussed a number of methods for overcoming this weakness of C or C++. The most useful and transparent method for the user of the function or library is to use pointer variables instead of arrays. The person using the library would write a program calling such a function by passing the address of the array and its dimensions as arguments. The person writing the function itself would use the pointer variable and increment it as needed to process the desired array elements.

This approach is most suitable if the array can be processed sequentially. It has the disadvantage for the function writer that the use of pointers and the need for sequential processing of the array can make the function itself difficult to understand and write.

However, the approach can be extended and simplified by using the preprocessor. It is possible to define a macro for performing an array-address calculation. Then elements of an array can be referred to with a convenient notation, and the function becomes much more readable.

To calculate the address of an element of the array, we need to add to the base address (for instance, the address of the start of the array), the number of elements in the rows before the current one, and the position of the desired element in its row. If a is the start address of the array, m the number of rows, and n the number of columns, the address of the i,j element will be a+i*n+j.

A suitable macro might be #define A(I,J) (*(a+(I)*n+(J))), where we are using the uppercase A to refer to elements of the array passed through the pointer argument a. Macros use a notation different from array references, one that will be familiar to Fortran programmers for the arguments. We can refer to an element of the array as A(1,3), for example.

This is not as fast as directly incrementing pointer variables, as John demonstrated, but makes the program easier to read--and will be applicable to a wider range of applications.

For example, an algorithm for matrix multiplication (Example 1) and its implementation in C (Example 2) show a direct correspondence of the lines, made possible by the use of simple macros for array references. Such a function can be called from a C program where the arrays are declared normally (Example 3).

You have to be careful if you try to mix such C functions with Fortran programs, because the two languages use different storage orders for the elements. Fortran holds the elements of an array column-wise, whereas C and C++ hold the elements row-wise. This, in effect, is a reversal of the order of the dimensions.

T. Graham Freeman

Australian Defense Force Academy

Reverse Engineering

Dear DDJ,

Regarding your editorial on reverse engineering (DDJ, March 1994), you're right in saying that most programmers end up doing some reverse engineering, but in my experience it is rarely out of choice. Most of us are not in the business of reverse engineering some system just to find out how it does some neat trick; we're reverse engineering it because we have to make our own code work with it. When supplied systems have bugs, or are incorrectly documented, or even undocumented, what is the alternative to reverse engineering? In my opinion, the European Community law has it right--when you have to make your code work with somebody else's system, you need to be able to reverse engineer. That's not lenient, that's common sense! But I'm prepared to make a concession. When someone delivers a system that is completely and correctly documented, and that is entirely free from bugs, I'll be more than happy to agree not to reverse engineer it.

John Hoyland

Swindon, England

One Ringy-Dingy_

Dear DDJ,

Your April 1994 editorial about Ma Bell hit a nerve. In November 1993, Southwestern Bell implemented a plan called the "Metropolitan Calling Area'' (or MCA), which is supposed to reduce our phone rates. Yeah, right! In St. Charles county, near St. Louis, SW Bell raised the basic phone rates 25 percent across the board in return for the ability to call places halfway across the state for free. (Well, free if you don't consider the 25 percent increase in your phone rates.) The way this was passed is that they held a series of meetings out in the sticks, asking people if they wanted the service. Of course, these people fell all over themselves as the 25 percent increase was a drop in the bucket compared to their long-distance bills to call St. Louis. Then evidently with this, SW Bell convinced the Public Service Commission (PSC) to raise the rates. Conveniently, they had only one public meeting in our area. SW Bell conveniently ignored the opinions of hundreds of thousands of people living close to St. Louis.

If that weren't bad enough, the plan wasn't fully implemented after the rates went up 25 percent. In the St. Charles area, the plan will not be fully functional until the fall of 1994. So for 8 to 10 months, we have to pay 25 percent higher bills and still pay long-distance charges to call the places we are supposed to be able to call for free. We are, in effect, being double-billed for the calls. SW Bell doesn't think that there is anything wrong with raising our rates to provide a service, then not providing the service. Letters to the PSC get double-talk responses saying that the plan can't be implemented all at once, and 8 to 10 months of double billing seems reasonable to them.

It's just like Lily Tomlin used to say on the TV show "Laugh In,'' "the phone company is omnipotent."

P. Lyle Mariam

St. Charles, Missouri

DDJ responds: Thanks for your note, Lyle. Subsequent to the April issue, Southwestern Bell began a similar push in the Kansas legislature (where it is the state's leading lobbyist) to free itself from the shackles of public oversight. Partly in response to SW Bell's efforts, both Missouri and Kansas are launching extensive studies to examine what their respective tele-communication system needs will be in the future. A Missouri bill has, in fact, proposed the establishment of a Commission on Information Technology which will focus on future telecommunication needs in the education and health fields.

Help for Help

Dear DDJ,

As the author of the Help Magician, I'd like to address "Help for Windows Help Authors," by Al Stevens (DDJ, April 1994).

Al made several negative comments about the 3-D interface. In talking to our customers, however, we find that the overwhelming majority likes the interface. Those who do not, however, are the most vocal.

Regarding Help Magician's functionality, in addition to entering the page number of the topic to access, the user can use Ctrl+PgUp and Ctrl+PgDn; click on the PgUp and PgDn button; or go to topic by title, context string, and context number.

It is not necessary to compile the entire help file to see the results of a particular topic. There is a One Page Preview function that compiles faster.

Not only are there left and right border functions, but complete paragraph formatting is available from the Paragraph submenu. Al did discover a bug. While I can't say that we've never had bugs, I can say that we fix problems the same day they are discovered and provide the customer with the help needed to continue working effectively. Help Magician has been on the market for about two years now and is very stable at this point.

In response to Al's request for a help tool that emulates WinHelp, our next release, Version 3.0, will have a WYSIWYG editor that will look like WinHelp, with a built-in test mode. It will also have a document-to-help conversion, a Visual Basic source-code scanner that builds a help- file shell, automatic glossary generation, a macro editor, a build-tag manager, and a more-standard Windows interface.

Robert B. Heberger

Foster, Rhode Island

Dear DDJ,

I agree with Al Stevens (DDJ, April 1994) that Help Magician's interface is a little too "3-D-ish." However, there is a checkable menu item that lets you turn it off. I also agree that the Help Magician approach isn't quite as polished as it might be--the paired markers are a little tough to work with, especially if you're importing an existing project; but if you're starting from scratch and have time to get more familiar with the tool, you can get used to it.

Al didn't address the issues of speed and support. I've used RoboHelp for years. Compared to Help Magician, RoboHelp is slow. With RoboHelp, lookups in list boxes for jumps can take forever on large projects or in multifile projects. Help Magician is lightning fast, especially when it comes to RTF generation.

On the support side, I've never worked with a company as responsive to developer input as the Help Magician folks. For instance, I found a small glitch on the sizing of the primary help window. When you enter 0,0,0,0 for location and height and width when controlling the color of the nonscrolling region in the main help window, Help Magician follows Microsoft's documentation and outputs a _,(0,0,0,0),, in the [Windows] section of the .HPJ file. Microsoft acknowledges this error in documentation, but that correction didn't get worked into the current Help Magician release. When I called them about it, I got a crisp, "You're right. We'll fix that immediately." When was the last time you heard a tool ISV respond that way?

Richard L. Warren

CompuServe 70750,3436

Varhol is Sent to the Office

Dear DDJ,

In reference to Peter Varhol's February 1994 "Programmer's Bookshelf,'' in which he states, "Wherever the school of the future ends up, we--as computer professionals--should be leading the way,'' please stick to programming and stay out of education. Heaven help us all!

No thank you Mr. Varhol, computer professionals should not be leading the way! Your industry is in its precious adolescence and does not have the credibility to lead any educational revolution. I applaud your interest, as a parent and citizen, to get involved in your child's education but as an industry--keep your collective butts at the programming desk until you get that right.

I apologize if I have overreacted to your article but either you wanted an overreaction and stimulated discussion or you are participating in the "lynch-mob'' mentality that is running rampant throughout the country. Your article is full of quasi-statistics that are fueling the feeding frenzy of criticism of the American educational system. Public education in America is not "broken.'' It works, everyday, everywhere!

I submit most educators (myself included) found the same thing you did. "I quickly concluded that LOGO was limiting and difficult to use compared to other [teaching tools] and set it aside.'' I don't know about your profession, but there is very limited time to adapt materials to classroom use. There are many tools (and certainly LOGO is one of them) that I would love to adapt to my classroom. It is a question of priorities.

Unfortunately, you can't complain about the high cost of education and then "fix'' the problem by spending more money. Education is expensive and will get more expensive and "doubling'' has no bearing, just more whipping up the fervor value.

Please, do get involved with your local school, but don't march in and tell us you have all of the answers. Try hitting a home run, first. Just sit down and write some simple program like "Carmen San Diego'' or "LOGO.'' Use your expertise, but use it carefully! Teachers may make some mistakes, but then the computer-programming industry is based on mistakes.

Ralph Hammersborg

Seattle, Washington

DDJ

DDJ welcomes your comments and suggestions. Mail your letters to DDJ, 411 Borel Ave., San Mateo, CA 94402, or send them electronically to CompuServe 76704,50 or via MCI Mail, c/o DDJ. If your letter is lengthy or contains code, we ask that you include a disk. Please state your name, city, and state. DDJ reserves the right to edit letters for length and/or content.

Example 1: Simplest algorithm for array multiplication.

for i = 1 to m
  for j = 1 to p
    C(i,j) = 0
    for k = 1 to n
      C(i,j) = C(i,j)+A(i,k)*B(k,j);

Example 2: C/C++ function using macros to simplify array references.

void matmul(int m, int n, int p,
   float *a, float *b, float *c)
   /* "a" is m rows by n cols,
      "b" is n rows by p cols, and
      "c" is m rows by p cols */ {
#define A(I,J) (*(a+(I)*n+(J)))
#define B(I,J) (*(b+(I)*p+(J)))
#define C(I,J) (*(c+(I)*p+(J)))
  int i, j, k;
  for (i=0; i<m; ++i)  {
    for (j=0; j<p; ++j)  {
      C(i,j) = 0;
      for (k=0; k<n; ++k)  {
        C(i,j) += A(i,k)*B(k,j);
     }
   }
 }
#undef A
#undef B
#undef C
}

Example 3: Main program to call the function in Example 2.

void matmul(int m, int n, int p,
    float *a, float *b, float *c);

main()
  {
    float aa[6][4],
    bb[4][7],
    cc[6][7];
    /* read numbers into aa and bb */
    matmul(6,4,7,aa,bb,cc);
    /* matmul(6,4,7,

(float*)aa,(float*)bb,(float*)cc);

will press the warning messages */ /* print cc */ }


Copyright © 1994, Dr. Dobb's Journal