Dear DDJ,
I could not bear to let Clyde Schechter's letter, Optimum Performance?, in the January 1988 issue go unanswered. It will leave young C programmers very confused about both multidimensional arrays and pointers.
Apparently Mr. Schechter has a two-dimensional array confused with an array of pointers. The definition:
int ary[10][10]
reserves storage for 100 integers, and the storage is quite contiguous. If the storage is not contiguous, then the concepts of pointer arithmetic and scaling in the C language have been built on faulty ground. The variable ary is an "array of 10 pointers, each containing 10 integers." The element ary[0][10] is the same element as ary[1][0]. No pointer variables have been created. The expressions ary, ary[0], and so on are all pointer constants. As pointer constants their values cannot be changed, meaning that they cannot appear on the left of an assignment expression. Rows cannot be swapped by swapping pointers, as Mr. Schechter implies. The distinction between pointer constants and pointer variables is fundamental to fully understanding the C language.
I think the definition he describes is:
int *ptrary[10]
ptrary is "an array of 10 pointers to integers." The storage for the pointers has been reserved, but the pointers have not been initialized. The storage to which they point is not yet present. Dynamic memory allocation can be used to obtain different amounts of storage for 10 different arrays, and each pointer can be set to reference one of the arrays. Now the pointers (array elements) can be exchanged.
Your readers should understand the difference between these next two expressions. ary[1][2] references element (1 10) + 2, element number 12, (the 13th element counting from zero), of array ary. ptrary[1][2] references element number 2 (the third element) of the array pointed to by element number 1 (the second element) of array ptrary. The scale of each row of ary is 10, while the scale of the rows of ptrary is unknown.
In support of Mr. Schechter, this topic is one of the most confusing aspects of the language. In C by Design, the college level textbook which I am co-authoring, we decided to devote one full chapter to discussing arrays, and another to discussing pointers. It required that much space to explain these subjects. I hope that this letter provided an adequate overview, and thanks for letting me express this opinion.
George Defenbaugh Jr.
Tulsa, OK
Your points are well taken, and you were not alone in your concern. We'd planned to have a reply from the author, Richard Relph, but last minute changes in the January issue prevented that. --Ed.
Dear DDJ,
One of the other editors here at BYTE pointed out Tyler Sperry's article in your January 1988 issue, "386 v. 030: The Crowded Fast Lane." I was inexplicable drawn to that article--maybe you can guess why.
In his article, Tyler summarized the conclusions I came to in my September 1987 BYTE article (in which I benchmarked a number of 80 x 86 and 68xxx machines). To quote his summary: "If you have some experience with benchmarks (or if you read BYTE regularly), you can anticipate what he [meaning: me] found: the 80386 outperformed the 68020 in the majority of tests."
I'm not sure how Tyler deduced that, but he's flat wrong. My article said: "Overall, it appears that--and I know I'll catch a lot of flak for this--the 80386 machines outperform the 68020 machines. Of course, the reason for this could well go beyond the possibility [my emphasis] that one processor is simply faster than the other." Nowhere have I made the claim that the 80386 processor performs better than the 68020. I'm surprised that Tyler interpreted "the 80386 machines..." as "... the 80386 processor..." My article was an attempt to reveal aspects of performance of systems based on processors, not an attempt to isolate processor performance.
Further down, Tyler states (in reference to the benchmark tests I ran): "...these tests were performed with the intent to test mathematical performance. The only nonmathematical tests were the infamous Sieve and a quicksort routine."
I've got to throw a flag on that one as well; check out two of the other tests I ran: Dhrystone and Fibonacci. Dhrystone is not a purely mathematical benchmark. It contains a mix of operations that involve indirect addressing, comparisons, array operations, and string manipulations. Nor would I consider Fibonacci's only goal to test math operations; it's main objective is to test the instructions involved in recursion.
All in all, Tyler's article was right on. I couldn't agree more with many of his "lessons." I've always admired the work DDJ has done, you people put out one of the finest computer magazines around. Keep it coming, and the other BYTE editors and I will keep reading it. (Just ask Tyler to read BYTE more carefully next time.)
Richard Grehan
BYTE Magazine
Peterborough, NH
Author Tyler Sperry replies:
Regarding your first point, I must apologize. As you point out, even though your article compared 386 and 020 systems you clearly warned your readers that the results could not be extended categorically. Although it could be argued this is exactly what most of your readers wanted.i As the later paragraphs of my piece made clear, both of us agree on this point. Apparently, my left brain took a vacation during the proofing and missed the gaff.
As to the benchmarks, I must confess that characterizing the Dhrystone benchmark as "mathematical" was a mistake. The single aspect of the Dhrystone is the strcmp function-it can affect compiler benchmark performance by as much 30 percent-and comparing strings isn't what most of us consider "mathematical." My mistake with the Fibonacci benchmark was a sin of omission; I consider the Fibonacci to be virtually worthless as anything other than a quick-and-dirty test for the a compiler handles procedure calls, and perhaps I should have spelled this out.
Despite these minor points, I think we agree on the broad issues. It's a pity we have to rely on benchmarks for comparisons of systems--or CPUs.
Dear DDJ,
Congratulations on giving OS/2 some decent coverage in the December issue of DDJ.
However, Dave Cortesi's article ("Dynamic Linking in OS/2," did contain one little flaw. He asserts that DLLs cannot be written in high level languages because of the requirement that SS = DS. In fact, Microsoft C has a switch especially to tell the compiler not to assume DS = SS, and Microsoft uses C to write many of the DLLs that are supplied with OS/2 and Windows.
Ray Duncan
Ex-member of the Happy DDJ Family
Marina del Rey, CA
Dear DDJ,
I appreciate your article describing the dynamic linking mechanism in OS/2. One minor correction, though. The current C compiler for OS/2 (at least the IBM and the Microsoft offerings) can indeed generate code for dynamic libraries. One must use the -Au and -Gs options. The -Au (usually -Alfu for large model) generates code for SS!= DS. Admittedly not all library modules are available (in particular the I/O library), but one can write shared code in C. With the -Au option the compiler generates a save and load for DS for each procedure. -Gs suppresses stack checking.
Also, a quick comment on your enthusiasm about the 80386. Yes, it is indeed a wonderful processor. But both OS/2 and the VM systems (Windows/386, Desqview and others) fail to fully exploit the chip. While the VM systems' value comes from compatibility with existing applications (not a minor point( they do not otherwise allow applications to exploit the processor. To fully exploit the native mode (also called protected mode) the path that OS/2 provides has the longterm advantage. Obviously, a merger of the two approaches is needed.
Robert Frankston (via CompuServe)
Author Dave Cortesi responds:
Duncan and Frankston are correct; both Microsoft C 5.0 and IBM C/2 support the -Au option. That generates code at every function's entry to save DS and load it with the selector for the data segment generated for the module, and code to restore the caller's DS on exit. As Frankston notes, the Gs option eliminates the check on stack depth, and that eliminates the commonest source of link-time references to unwanted library procedures.
These options are, however, peculiar to the particular compilers. The IBM Pascal/2 and comparable Microsoft Pascal compilers do not have them, and other C compilers might or might not. And while the features help, they don't fill all the potholes on the road to dynamic linking.