Departments


We Have Mail


Dear Sir:

I am a computer science instructor for one of the numerous universities that use Pascal as the primary teaching language. Recently, at a curriculum planning group meeting, I suggested that we give serious consideration to adopting C as our primary language. For a brief time I replaced the USSR as America's principal adversary. All sorts of reasons, including difficulty and treachery, were paraded as reasons why we shouldn't even consider such change. And yet I persist, for I feel that at graduation CSS students should take useful knowledge into the world.

Now, the question: do you good folk at The C Users Journal know of any schools that currently use C or contemplate using C as their primary language? If there are any, I need to review their experience and particular problems, so that I can make a better case for my own agenda. Please tell me what you know. I will appreciate it.

Sincerely,

Casy Ver Berkmoes
Coordinator, Undergraduate Computer Science Department
The University of Southern Mississippi
Long Beach, MS 39560

I suspect P.J. Plauger might answer this differently, but since I'm here and he's in Europe, and I've taught quite a bit of introductory programming, I'll slip in my two cent's worth.

I don't recommend using C as a primary teaching language, for several reasons.

-C is not a "safe" language. The lack of run-time type and bounds checking allows the student to commit errors that can't be found without fairly advanced understanding of the run-time environment. It's not reasonable to make an understanding of compiler code generation, operating system linkages, assembly language debugging tools, and other advanced topics be a prerequisite to effective debugging. Not only will students fail to find the bug, the seeming randomness of certain C bugs will encourage students to trust to uncontrolled trial and error debugging and foster a belief in "black magic" explanations.

-Appreciation of some of C's most important strengths requires extensive knowledge of the environment. Separate compilation, direct manipulation of the hardware, ease of assembly language integration, bit-wise operators, pointer/array equivalences — these are some of C's greatest strengths, but are not even remotely related to the kinds of problems with which a beginning student should be struggling.

-Many important effects are achieved through non-obvious means. For example, by putting subsystems into separate files, creating the right kinds of headers, and labelling certain functions static, the programmer can create an encapsulated type. The indirectness of the implementation only complicates the teaching of the core concept — a concept that is fairly difficult to communicate anyway.

-The elegance of the language can't be appreciated until you've tried to solve fairly demanding problems in other languages. A student who is asked to do classroom exercises in C will probably invest a lot of energy asking "why can't I just have a string type". On the other hand, the student who has tried to pass a Pascal string to a "Pascal-hostile" operating system will just be thankful he has the tool. It's unwise to push the advanced tool onto the student before they've experienced at least some of the situations that created the need. Otherwise, the student isn't developmentally prepared to internalize the nuance of using the tool.

Having said all this, I must admit that I have talked with faculty who use C as the primary teaching language. Unfortunately, I don't recall any names. If they are reading, I hope they'll contact you and share their experiences. — rlw

Dear Mr. Plauger:

With regard to the article "Doing Fractions in C++" in the November 1991 issue, I found the topic to be interesting and relevant, and commend Mr. Zeidler for doing the programming and writing. Unfortunately, Mr. Zeidler did this work while learning C++, and made a serious mistake in his design. I am afraid that his mistake may be duplicated by other C++ newcomers who read the article; hence this letter to point out the problem and propose an alternative.

The problem I am referring to is the class structure that has the fraction class inherit the gcd_cls class.

Actually, the gcd_cls should not have been used at all. A gcd is simply a number (integer), and the gcd operation is performed on two integers. In C++, the compiler handles integers (or longs in the case of these fractions) as an elementary data type. The gcd operation should be introduced simply as a function with two unsigned long arguments that returns an unsigned long, thus extending the set of functions available to operate on the built-in unsigned long data type, as in

unsigned long gcd ( unsigned long, unsigned long );
A fraction is not a special case of a gcd. There is a relationship between fractions and gcds, but only in the sense that the gcd operation (function) is needed to help keep fractions in simplest terms.

Why all the fuss, if the approach used by Mr. Zeidler "works?" Well, it works, but incorrectly. Each fraction instance contains the numerator, the denominator, plus an instance of gcd_cls. An instance of gcd_cls contains three unsigned longs (u, v, and r). In a typical implementation, these fractions would require 20 bytes of storage, instead of only the eight bytes a proper design would need to store just the numerator and the denominator. Obviously, the storage needed by the gcd function does not have to be present in every fraction, and can be obtained (automatically) from the run-time stack when the gcd function is called.

If we want to keep this particular gcd function separate from any other gcd function that might be lying around in a library somewhere, it would be acceptable to implement gcd as a member function of the fraction class. In that case, it might be implemented as function that returns the gcd of the denominators of the two fractions, as in

fraction3.denominator = fraction1.gcd( fraction2 );
Inheritance is an especially attractive feature of object-oriented programming and C++, but we must not let ourselves fall into the trap of using it inappropriately because it usually has a cost associated with it. One simple test that may be applied is to ask whether the new class is a special case of the inherited class. If not, then the proposed inheritance is wrong.

Sincerely yours,

Herbert R. Haynes, Ph.D.
6630 Pharaoh Dr.
Corpus Christi, TX 78412

Dear Editor,

Reading your journal always gives me a real pleasure. I read it from cover to cover, but articles about programming concrete problems in C are of great interest to me.

I should like to thank you for the series "Doctor C's Pointers" and Stuart T. Baird's article "Using Large Arrays In Turbo C" in January 1991. It was very useful to me. I'm also interested in the shareware of The C Users' Group, but it's absolutely unattainable for me.

The lack of attention to programming artificial intelligence in low-level languages, specifically to expert systems, is regrettable. If you are interested, I could offer you a programming example of a simple rule-based expert system in C.

It is also regrettable that The C Users Journal is not widely available in Russia. Despite the fact that it is only accessible at a few libraries, it is very popular in Russia. I would be very glad to expand the readers' circle of your journal in Russia.

Warmest Regards,

Dmitry N. Ivanov
Udaltsova, 57-43
Moscow, Russia

I assure you we've made no editorial policy against AI in C. In fact, AI is one of my personal interests. I should think a rule-based system in C would be very interesting — but remember, the overall quality of the manuscript is always the determining factor in whether a story gets into print.

The biggest reason we haven't run much on AI is that we've seen few good AI manuscripts. I take that to be an indication that AI is still finding limited application. — rlw

Dear Mr. Plauger,

It was with a great deal of interest that I read yet another reply to my August 1991 request for help with defining/declaring global variables. The comments and suggestions from both yourself and readers have been most helpful. Dr. Purdum's method is one I have been using for quite some time: it works well, and seems to be in common usage. The method proposed by Terence Griffin (November 1991, p. 131) which uses a macro instead of a #ifndef/#endif to accomplish the same end result seems to be a bit cleaner, however I've not yet used this technique. And of course, the method you've suggested is also very workable; however I don't favor it since it places the declaration and definition in separate files. I suppose that this variety of solutions is just one more example of the numerous ways to accomplish the same thing in C (and yet another example of why C is so confusing to newcomers).

But "how to define a global variable" was not my original question. Perhaps I did not phrase it clearly enough, but I do believe that my question is important enough to look at again. In my example I had a large number of source files and the customary number of global variables declared and defined in a common header file. One particular file, containing the macro processing functions, had a number of global (to that file only) variables defined in it. As a matter of fact, the way the files and functions were broken down, all the variables for macro processing were confined to that particular file — the functions in the other files had no need to know of the existence of any of these variables. To me, this presented a neat and tidy package with all the variables defined in one block.

The problem which came up was that one other function (an error trap routine) needed to know the value of one of the macro processing variables. I presented my solutions to this problem — all of these work but I wasn't pleased with any of them. I suppose it boils down to a matter of programming style and just how defensive one wishes to be. I was looking for comments from others who've dealt with this, surely not uncommon, problem.

Hope this clears up some of the puzzlement over the debate.

Yours truly,

Bob van der Poel
Bob van der Poel Software
P.O. Box 57
Wynndel, B.C.
Canada V0B 2N0