Departments


We Have Mail


Dear Mr. Plauger,

I just discovered that my letter to the editor got published after I received a letter from someone looking for more information about real-time systems. I bought a copy of your magazine and read your response to my letter, prompting this reply.

I didn't intend for my words to be harsh, but I was trying to make a strong point which, by the way, seems to have been missed by you also. Writing an article on real-time without mentioning terms such as deadlines is like writing an article about compilers without mentioning the word parser, even if only to say that the article will not address issues of parsing.

You said, "I feel he is a bit harsh on Champlain's article for not stressing those issues as much as Mr. Jameson would like." As much as I would like? None of the issues were even mentioned! I don't expect a deep tutorial on real-time any more than I would expect an in-depth tutorial on compilers. That is not the purpose of your magazine. If such information is required, one looks in the appropriate journals or text books. But suppose there was going to be an article on code generation (say). I would hope that such an article would start something like, "...A compiler is a program consisting of a parser, to recognise an input program, and a code generator, to produce machine language from that program. In this article we will address issues of code generation, optimisation...," and so on.

Your klystron analogy totally misses the point. As I tried to explain in my letter, speed of operation is not the issue. It doesn't matter how much spare capacity is available in your four-bit chip if the process "protecting" the klystron is blocked by some other process. It won't run, it will not pass GO, it will not protect your klystron!

You mentioned "hard" real-time, although I was not referring specifically to such systems. Although the difference between hard and soft real-time systems is often fuzzy, it really boils down to what happens if a deadline is missed. Thus, if I have a computer controlling the temperature of my bath and I want the water to be at 80 degrees in five minutes, I can cope if the water gets to 79 degrees or if it takes six minutes to make it to 80 degrees. However, I'm not willing to wait 10 minutes to get the desired temperature. Thus, an average response time of five minutes is no good if the worst case can be 10 minutes. However, an average response time of three minutes with a worst case of six minutes would be acceptable. Thus, even this "soft" real-time system has deadlines that must be met. I repeat my statement from my original letter: Champlain's system may be fast, it may have lots of threads and fast context switches, but if it cannot provide guaranteed response times, it is simply not a real-time system by definition.

As the editor of what is generally an excellent magazine, I think you have a responsibility to your readers to provide accurate information. Champlain's article (and your response to my letter) give the impression that all you have to do is provide lots of CPU cycles, be efficient, and voila, you have a real-time system. It simply ain't so!

Cheers,

David H. Jameson
Research Staff Member
Department of Mathematical Sciences
IBM Thomas. J. Watson Research Center

Sorry to ruffle your feathers because I agree with a lot of what you say in both your letters. I think you missed my point a few times. I would happily print an article that discusses compilers without mentioning parsers. Granted, it would be more complete with such a mention, but I don't consider that a fatal flaw when addressing such an enormous topic. Real-time is an equally extensive topic.

One way I oversimplify real-time for beginners is to describe three levels of consideration. First, a system must be fast enough to do the job — that's raw speed. Second, it must be safe enough — synchronize activities so as not to corrupt data or deadlock. Third, it must be predictable enough — you have to convince yourself that it will do the job, even with worst-case timings. The point I tried to make in my last response to you involves all three levels. If you focus on getting the synchronization right, often the other two levels take care of themselves. A system that is blindingly fast (compared to required response times) and that doesn't deadlock will probably have adequate worst-case response. How precise you need to make "probably" depends on what's at stake. Human lives are worth more than klystrons, for example.

Once more, I agree with the points you made about the importance of predictable behavior. You can still cover lots of useful material about real-time systems, however, without getting around to that topic. Maybe to you that's real-time "by definition." I find the hardest thing about teaching real-time is getting everyone to understand their own definitions of the term. After that, getting everyone to agree on a common definition is easy by comparison. — pjp

Dear Mr. Plauger,

Thanks for your excellent Standard C column. I find it first read, and most often referenced. It was a pleasant surprise to find you editing The C Users Journal, and my enjoyment of it has increased even more under your guidance.

I would like to point out a minor flaw in your March 1991 column on <locale.h>. It's not about C (which I defer to the experts, such as yourself), but to the statement saying "Americans enjoy the luxury of a single (official) language." Unfortunately, Americans (for the most part) only enjoy a common language, English. It is not the official language of the United States of America. We don't have an official language! Nowhere in the constitution, or in the other laws of the country is English, or any language, listed as the official language of the USA. It seems odd that Americans can standardize and make a computer language "official" like Ada, yet we can't agree that English should be the official language of the USA.

You might want to make your readers aware of U.S. English, an organization dedicated to the adoption of English as an official language of the USA. Their address is 818 Connecticut Ave, NW, Washington DC, 20006, (202) 833-0100.

Good luck down under, and keep up the good work.

Sincerely,

Bruce Wells
190 Garth Road, 6Q
Scarsdale, NY 10583

Yup. I caught that error even as the ink was drying. I dunno what practical effect it would have to make English official. (I read once that the first U.S. Congress came within one vote of making German the official language. Gott im Himmel!) Personally, I would like to require grammatically correct English of all politicians. That would thin their ranks. I share the common writers' prejudice that sloppy speaking reflects sloppy thinking. Clear thinking isn't sufficient for a competent politician, but I wish it were necessary. Good luck. — pjp

Dear Mr. Plauger:

I found at least four instances in the May 1991, C Users Journal in which the universal constant, pi = 3.14159 . . ., was assigned its value discretely. That is, the authors of the listings defined the value of pi digit by digit. There is a simpler, more reliable way to introduce pi into any program, a way which assures the programmer that the assignment is accurate to the capability of the compiler/interpreter. Define pi using this statement:

pi = 4.0 * atan(1.0);
This constant is very common in numerical applications. Even for those who take pride in remembering pi to its umpteenth decimal place, errors can slip in. The statement suggested here makes it simple for non-numerical programmers and DSP experts alike to avoid any error.

Sincerely,

Robert H. Penoyer
123 North New Avenue
Apartment D
Monterey Park, CA 91754

Yup. pjp

Dear Mr. Plauger,

Regarding Mr. Wiedmann's letter (May 1991) with details about how to handle configuration data in an EXE file. It seems that the number returned by the POSITION macro must be adjusted by the size of the header information in the EXE file. This letter contained just what I needed but I was a little suspicious when I did not see any adjustment to the seek value to allow for the size of the header information. Mr. Wiedmann's method works great if the definition of POSITION is changed to:

#define POSITION \
 (((exe_header.header_size << 4) \
 + (char huge *)&config_data) \
 - (char huge *)MK_FP( _psp, 0x100))
Every issue of CUJ has a little gem like this one that more than pays for my subscription.

Does CUJ have a FAX number or a BBS that readers can use for stuff like this?

Thanks,

Joe W. George
4208 Lentell Road
Eureka, CA 95501

We are still debating the costs/benefits of a BBS. Meanwhile, keep those cards and letters rolling in. — pjp

Dear Mr. Plauger,

I noticed that in his article on data structures (April 1991), Rex Jaeschke used the construct:

switch (toupper(inchar = getchar())){
My own experience is that this can cause problems depending on how toupper is implemented. Some compilers (such as Turbo C V1.5) implement it as:

#define toupper(c) ((c) + 'A' - 'a')
which would work fine in the above example.

However, to save programmers the bother of checking that the argument is a lowercase character, other compilers (such as MCC68K V3.3) implement it as:

#define toupper(c) \
   (islower(c)?((c) + 'A' - 'a'):(c))
In this case, the argument is evaluated twice: once in the test and once in the conversion. When the argument is getchar(), the result is that only alternate characters are processed (or that every character needs to be input twice). I don't know whether ANSI says anything about how toupper should be implemented, but if not, the problem is easily avoided by writing two statements:

c = getchar();

switch (toupper(c)) {
Although this can require an extra int to be defined, it's safer and more portable.

Yours sincerely,

Anthony W. Leigh
13 Priory Walk
Portbury
Bristol
BS20 9TJ
England

Standard C requires that all macros except getc and putc evaluate each of their arguments exactly once. Rex's form is now safe. Your approach is better for code that may have to compile under an older implementation of C. — pjp

Dear Editor,

I read the article "More Accurate Linear Interpolation" by J. Forkosh with some interest as I have been researching functional approximation for some 25 years and am interested in any and all algorithms on interpolation and approximation. If I may, I should like to make some observations that may help readers who need to solve the problem addressed by this article.

First I must disagree with the title. The writer of the article considers the problem of approximating a function by a sequence of straight lines not the interpolation of a function, correctly arguing the inaccuracy of that approach. The actual problem that is addressed is the least-squares approximation of a function by linear splines with fixed knots, which has a well-known solution. Regardless of the semantics, the major problem is mathematical. It cannot be stressed too strongly that the least-squares norm is never the correct norm to use for functional approximation or for data approximation. In the case of approximating functions where the value of the function is known exactly (at least to the last few bits) then you have to minimize the maximum error. That seems to be very obvious. For data approximation the errors in the data do not form a normal distribution (do not let statisticians tell you otherwise) so it is more appropriate to use the L1 norm. These are basic guidelines for anyone manipulating data and functions.

A further comment, which does not detract from the article because of its complex nature, is that of variable knots. The algorithm assumes that the X values are given and then computes the Y values. What happens if you wish to make both the X and the Y values variable? To properly minimize any error criterion, this is exactly the problem you need to solve. This variable knot problem is non-linear and, therefore, more complex. However, there are solutions. If your readers want one solution to this problem then consult "Fitting Curves to Data," (The C Users Journal, January 1990) and "An Adaptive Data Analyzer" (The C Users Journal, May 1990). The methodology presented in these two articles can be easily extended to functional approximation.

Sincerely,

Michael Brannigan Ph.D.
15 Normandy Court
Atlanta, GA 30324

You obviously know much more than I about approximating functions. I like the least-squares norm because it is easy to use. I know that it doesn't give ideal fits, but they are often good enough. The other articles you cite are well worth reading as well. — pjp

Dear Sirs:

Several members of our software staff have recently come upon what we call a "Why can't I do that?" situation. What we would like is for C to support bit variables as opposed to bit fields. The code in Listing 1 demonstrates our desire.

While the current method does get the job done, the flags really just seems to add characters to the source file and does not add any additional definition to the individual flags. We have, in the past, followed the flag structure declaration with several #defines:

#define ALARM_ON flags.alarm_on
#define DOOR_AJAR flags.door_ajar
This method seems to get us closest to what we really want. Is this as close as we are going to get? Also, is there a reason why bit variables were not implemented in standard C since it seems the designers were so close with bit fields?

Thanks,

Mike Brungs
Cincinnati Time Inc.

If I recall correctly, Dennis Ritchie added bitfields to C only grudgingly. Seems some people at AT&T Business Information Systems wanted to fiddle the unused bits in a pointer on a Sigma 5 computer. They insisted on being able to declare bitfields to do the job. I think Dennis was right to hide such nasties within a structure. That's the place to put a sequence of related declarations. It's also important to maintain the principle that all data objects consist of a contiguous sequence of bytes (possibly with holes that don't contribute to the value). That's harder to keep clean with bitfields all over the place.

I could argue that you don't want to do what you say you want to do, but I won't. I find such arguments specious. Instead, I observe that language designers must make compromises. Dennis is much better than most at making such tradeoffs. With C, he has made many of us very happy most of the time and all of us annoyed only some of the time. That's not bad. — pjp

Dear Dr. Plauger,

The April issue of The C Users Journal has a couple of errors, that really jumped out at me.

On page 46 ("Of Mice and Menus") Keith Bugg states that you must buy MOUSE.LIB to program for the mouse in MS-DOS. This is not true. Microsoft C and Borland C products may both access all mouse functions without using the MOUSE.LIB. This may be done through int86 calls, or in-line assembly (and other methods).

Most mouse functions require setting up and/or reading one or more of the resisters AX, BX, CX, and DX, along with a call to the mouse interrupt (0x33). Mouse functions 9, 12, 16, 18, 22, 23, 24, and 31 also use the ES resister and will take some extra work. (By the way, does anyone know what mouse function 18 does?)

The listing starting on page 47 makes many calls to the function mouse, but no such function (proc) exists in MOUSE.LIB. MOUSE.LIB instead contains six functions for various languages and memory models. They are mouses, mousel,_cmouses, cmousem, _cmousec, and _cmousel. In my programs, I use a #define at the beginning of the program to resolve this. For example, in small or tiny model programs, I would write:

#define mouse cmouses
See Listing 2. The next thing that hit me was near the end of the article "Point-And-Shoot Menus" (page 62), in which the author says, "This example of point-and-shoot menus was implemented in ANSI C to enhance its por- tability." Wrong!

The program CUJMENU.C includes the following non-ANSI (Turbo C) functions: gotoxy, textcolor, putch, cputs, gettextinfo, _setcursortype, text- background, clrscr, and cprintf. While some of these functions exist in Microsoft C as well as Turbo C they have differences which would make them totally incompatible in this situation.

CUJMENU.C includes the following ANSI functions: strlen and toupper. So then, lets see, that's two out of 11 are ANSI, not bad!

Sincerely,

W. Paul Mills
4638 N.W. 35th St.
Topeka, KS 66618-3609

The author replies:

The Microsoft library MOUSE.LIB is not actually needed to make mouse calls. As long as it is Microsoft compatible, listed as a device in CONFIG.SYS, the driver loaded, etc., the function mouse in the enclosed sample program will work. For any mouse function which returns a value (e.g., button presses, cursor location, etc), the user needs to set these up as seperate functions (mine are left_but_up and right_but_up in the sample program).

Keith Bugg

Gentlemen:

When I made a subscription inquiry to your magazine I was sent the November 1990 issue as a "tickler." I've since sent in my check and am pleased to be a subscriber. But an article in the free issue kept nagging at me. I refer to "A Flexible Dynamic Array Allocator" by Dick Hogaboom. "What a clever idea," I kept thinking — at the same time the other part of my brain kept telling me that the routine could not work.

I finally found some time the other day to type in the listing and confirm my suspicions. It doesn't work! The routine is quite clever (perhaps too much so) in that it adjusts the pointer returned so that it is biased for non-base zero arrays and, supposedy, for the secondary dimensions of the array. The flaw in the logic is that the compiler, no matter how smart it might be, cannot calculate the correct offset for the second (and subsequent) dimension(s) unless it knows the size of the first one. And by size, I refer not to the size of the pointer, but to the actual amount of memory required for each row of the array.

Listing 3 illustrates the problem. The only way an allocator of this type can work is for it to have a companion function which will return a pointer to the desired array element. This function would need to know the size of each element in the array and the number of elements in each dimension (except, perhaps, the last one). This would not be as quick as the routine presented in the article, but it would work.

Now, a question: I have been working on a large program for the last six months. The source code is contained in about a dozen files; all of the global variables, etc. are contained in a common include file. When I started this project (a text editor) I was determined to hide as much data as possible from functions which had no need to know and to write the code in a logical, readable and maintainable format. For the most part I'm pleased with the results. But a nasty bug hit me the other night and the sun was starting to come up by the time I found the problem. In the file keyboard.c I had defined a number of variables dealing with the keyboard buffer and some macro key processing functions. They were all defined as static, making them unknown to the other files. All, that is, except for one. This variable, maclevel, keeps track of the current macro key nesting level. If its value is zero no macros are being processed. A few other functions need to know if a macro is being processed. It was simple to declare maclevel in the respective files as an external variable. So far, so good. But somewhere, over the long development period, I changed maclevel from an int to a char. At least, I did so in keyboard.c; I neglected to do the same for the external declarations. Of course, accessing a char variable as an int will cause all kinds of grief!

The solutions I've come up with are:

1. Use a lint-type program to check on oversights. But I don't have such a program, and even if I did it seems like a cop out.

2. Be much more careful when changing variable declarations. But, I'm only human.

3. Avoid the use of extern and place variables like maclevel in the common include file — a solution I don't like since it is nice to have all the variables relating to a task in one block. This solution would take one of the many variables needed for macro processing out of the block.

4. Avoid the use of extern by having a function which returns the value of the variable. In this case, the function getmaclevel is contained in keyboard.c and simply returns the value of maclevel.

I've elected to use solution 4. But I'm not entirely happy with this tradeoff. It seems that in the interest of "nice code," I've had to pay in increased code size and a slower program.

Do you or you readers have another solution to this problem?

By the way, I'm really enjoying the magazine. Keep up the good work.

Bob van der Poel
PO box 57
Wynndel, B.C.
Canada V0B 2N0

All of your approaches are valid ways to deal with the problem. You can also use a C translator that checks type compatibility across translation units — Standard C permits such checks but doesn't require them. Or you can switch to C+ +, which makes such checks as a matter of course. I use a minor variation on your #3 — declare the shared data object as an extern in a header that you include in every file that accesses or defines the data object. Define the data object in exactly one of the files. That gives me the combination of efficiency and consistency checking that I want, even in the presence of weak checking at link time. — pjp

Dear CUJ,

I'm always glad to see a new issue of CUJ in my mailbox, and the May issue was no exception. I particularly enjoyed reading Hans Zwakenburg's excellent article, "Inexact Alphanumeric Comparisons." This is an excellent example of a simple technique which ought to be more widely used, but most of us practicioners aren't aware of because the information is buried in obscure and obfuscated academic journals. I thought, however, that there were a few points that should have been expanded. (I hope this isn't taken as a criticism!)

First, there are a lot more potential applications than searching data bases. For example, whenever a user is prompted for a file name, and he or she makes a minor error entering it, most programs just give a "no such file" message and loop. Far better to automatically scan the directory and find the file name the user meant: the one closest to the typed-in name according to edit distance. Or in parsing keywords on command lines: if there is no exact match found in the list of expected keywords, search for a good inexact match!

Mr. Zwakenburg's source code appears to have been written for maximum clarity, and contains many opportunities for optimization — like expressions evaluated multiple times in macro expansions — most of which will be obvious to experienced C programmers. There is one very important optimization that might not be so obvious to most readers: the array distance does not have to be two-dimensional! Since, as Mr. Zwakenburg points out, the data flow is like a spreadsheet that always flows from top to bottom and left to right, only the most recent row of the matrix needs to be retained. The optimized memory requirement is proportional to COMP_LEN, not to its square. I have taken the liberty of rewriting ld.c with this and other optimizations, and the new source code is enclosed. See Listing 4.

An important caveat to readers of the article: By setting the addition weight very low and the deletion weight very high, this implemention of Levenstein Distance is not symmetric! For example, l_distance("foo", "foobar") returns 3 but l_distance("foobar", "foo") returns 15. In other words, the weights are biased in favor of the "requested" string being a substring of the "found" string and biased against "found" being a substring of "requested." This might not be the behavior you want, depending on your application. The calculation becomes symmetric and truly a distance measure in the mathematical sense when the addition and deletion weights are the same.

The algorithm can be enhanced by providing a more complex function for character substitutions. Instead of a single weight value for any change, there could be a low penalty for a change of case ('B' versus 'b'), a medium penalty for substituting one vowel for another ('e' versus 'a'), and a high penalty for changing a numeric digit. Designing a good set of weights requires some craft and a good understanding of your application.

Mr. Zwakenburg does not give an explanation of how the algorithm was derived, or a bibliography. Some of your readers might be interested in:

1. Wagner, Robert A. & Fischer, Micheal J., "The String-to-String Correction Problem," Journal of the ACM, Vol 21, No 1, Jan 1974, pp. 168-173 which is reprinted in:

2. Srihari, Sagur N., editor, Tutorial: Computer Text Recognition and Error Correction, IEEE Computer Society Press, 1985

Sincerely,

Jim Conyngham
Buffalo Computer Graphics
7403 Newhall Lane
Austin, TX 78746

Inexact matching is a subject with seemingly endless applications, and ramifications. I appreciate the additional information. — pjp

Dear C Users Journal,

I am the representative of a very new, private Romanian company of consulting engineers, and I write to ask your readers for help.

After the Romanian revolution in December 1989, we considered that it was vital for Romania to try and turn its economy from a bankrupt socialist system into a market-driven economy. One area where we realized desperate and particular attention needed to be paid was in computers and computing techniques.

Twenty of our best software and hardware engineers from Constanta — drawn from computer centers, universities and other enterprises — set up this agency. But the first major problem we face is a severe lack of scientific books, manuals, magazines and catalogues.

We consider that one of the most effective means of ridding our country of the terrible memory of Communism is not simply by appealing for clothes and food, but for help in improving their education. That way we can improve our standards in industry and commerce, and help our people to make the things they need for themselves.

We would be very grateful if any of your readers would donate books and software, which is particularly expensive for us. Perhaps even make us a subscription to their favorite magazine, or even send us old issues that they no longer need.

Thank you very much for publishing this appeal, we look forward to hearing from you soon.

Please remember this old Chinese proverb which says: "Give a man a fish and you feed him for a day, teach him to fish and you feed him for life."

Many thanks to you.

Aurel Cartu, Manager,
Consulting & Engineering Agency,
Aleea Brindujelor Nr. 2,
Bloc L9,
Sc C, Ap 45,
RO-8700 Constanta
Romania

As administrator of a non-profit association called AIDE (HELP in English) which stands for Assistance aux Informaticiens et Dbutants Europens, I was the person who received this appeal with a mission to make it known to all and every one in the computing community. I went to Constanta at the end of March with some hardware and software and can only say that your help will be most needed. As of April 1, the prices have been multiplyed by three, while salaries only went to double! idea to send subscription to magazines directly to Aurel.):

Guilain Devillers,
Administrator of A.I.D.E.
P. O. Box 54
L-8001 Strassen
Luxembourg
Phone (+352) 312 721
Fax (+352) 312 613

Sounds like a good idea to me. All volunteers are welcome. — pjp

Dear Dr. Plauger,

Just a quick note on a couple of points relating to The C Users Journal. First, the pat on the back. I am a voracious (but selective) reader of a wide range of computer mags and journals. Some get a cursory scan for the odd useful bit, some I read a lot of, but only two get read cover to cover. These are CUJ and Embedded Systems Programming. As a professional software engineer, I find CUJ the most consistently useful and readable journal of a large sample.

Second, I have written a separate letter to Rex Jaeschke about his recent series of C Puzzles. I enjoyed them enormously. I thought they were entertaining, stimulating, and highly educational. I would love to see them as a regular feature.

Finally, I know space is at a premium in any magazine, but would an "Information Wanted" column be possible? it is done informally and to a limited extent already. The idea would be for readers to canvass other readers for information. If you restricted the inquiry to, say, 30 words plus address then you could fit a lot on a page. My own would be:

Experienced programmer, new to Real Time wants suggestions for good texts on starting Real Time OS, kernals. Any known PD code, examples? (Address as shown below.)

Meanwhile, keep up the good work. Hope you enjoy your year in my homeland.

Ian Cargill
CPEng, MIEAust, MIEEE.
1A High Drive
Oxshott
Leatherhead
Surrey
KT22 ONG

So far, this letters column seems to be serving as the community bulletin board you envision. Should the need increase, we will happily reconsider our format, however. And yes, I am enjoying my year in Australia. Americans seldom get a dinkum opportunity to practice speaking a foreign language. pjp

Dear Mr. Ward:

Your Editor's note in my article "Complex Function Library" (CUJ, September, 1990) has generated a lot of thought on my part over the succeeding months. The return of structures in the complex function library is a special case in which it appears to me that the inefficiencies involved are worth it due to the increased clarity of the source code. This is, of course, a subjective opinion, and other programmers faced with different environments and conditions might validly decide against using the library.

What about the general case? If the return of structures is eschewed in order to avoid alienating older compilers, what about the use of hexadecimal constants, the initialization of automatic arrays and other features of Standard C not found in the first edition of K & R? I suppose the answer is again subjective and depends on what is envisioned for the code being written. I have written code which is devoid of hex constants because I knew it would be ported to an older compiler. On the other hand, I usually make use of such constants because most of what I write will probably never be presented to non-ANSI compilers or, at least, not to compilers which do not speak hex.

I believe a case might be made for returning structures in order to hide functions from one another. The pass-by-value feature of C and the ability of a function to hide its local variables from the outside world are frequently pointed out as beneficial in separating the environments of the calling and the called functions. A calling function may pass, and a corresponding called function accept, numerous variables which are passed by value. The calling function need not know the names of the parameters used by the called function nor anything else about the way such variables are handled by that function.

The called function may, however, return only one variable, usually of basic type. It might be of advantage in isolating the called and calling functions from each other to be able to return numerous variables to the calling environment by value. One way to do this is to embed the values to be returned in a structure and then return that structure by value. This would seem to be of primary worth in hiding the details of the calling environment from the called function, while passing by value hides the callee from the caller.

Consider, for example, scanf. That function is not an entirely realistic example because the number and types of variables to be assigned values is not constant. It is, however, a familiar function and if one pretends for the sake of this argument that it accepts a fixed number of parameters of predetermined type it will do for the following example.

scanf is a function which must assign values to numerous variables. It must be passed addresses so that it can write the values to be returned into the spaces designated by the addresses. scanf must therefore have access to memory controlled by the calling function. If scanf runs amok, it may write data into areas other than those intended by its caller.

If scanf were rewritten to return a structure, the information passed from the calling function would be format information only. scanf would act on that information and assign appropriate values to the elements of the structure prior to returning it by value. scanf would need to know nothing about the calling environment, including the addresses of the variables for which values were being sought.

Is there any merit in this? I don't know. I suppose that your note pushed me into thinking about it and that it appears to me intuitively that there is a symmetry lacking between the methods for passing values to functions and the methods for returning values from functions. I would expect that in most cases a function, like a mathematical equation, will accept multiple arguments (independent variables) but will return only one value (the dependent variable). In such cases, the asymmetry noted above is not important.

One must be cautious about what is meant when a compiler returns a structure. The manual for one compiler notes that structures may be assigned, passed as parameters to functions or returned from functions. The manual cautions, however, that the return is accomplished by copying the structure into a static local variable and then returning a pointer to that variable. Such a scheme will make the function non-reentrant.

From a protocol standpoint, I must note that I addressed this letter to you because you wrote the original note, not to bypass Dr. Plauger nor to infer that he is doing other than a very fine job as Editor.

Keep up the good work.

Sincerely,

Maynard A. Wright
6930 Enright Drive
Citrus Heights, CA 95621

I don't feel bypassed. Your letter makes several good observations. I agree that Standard C is now sufficiently widespread that we should use the full language by default. Truckle to old compilers only when you know you must. Having a function return a structure is often the most natural, and efficient, and safe, way to do the job. By the way, the C Standard requires that functions returning structures be reentrant now. — pjp

Dear Mr. Ward:

The reason I am sending this letter along with payment is to let you know that I came very close to returning the first issue (May 1991) instead of a check. I was really put off by Plauger's editorial and think I should let you know why. Actually, I could care less what you call the journal, but I do care about its content. There are endless resources out there for those who want to hone their C skills, including dozens of technical books, excellent college textbooks and treatises on all manner of specialized applications. There are, however, precious few resources for exploring what we are told is the leading edge of C's development, namely C++.

When Plauger writes that you "try to run at least one article in each issue on C++", I knew I had made a mistake in subscribing. I don't want to belabor the point, but you are going to have to get a lot closer to "trying to publish at least one article on C+ + in each issue", or I will certainly not be with you for a second year.

Yours Sincerely,

Ralph Ewton
The University of Texas at El Paso
Department of Languages and Linguistics
El Paso, TX 79968

Sorry, but I think that C++ is just one of the leading edges of C's development. At the risk of ruffling Robert's feathers, I can tell you that competing publications exist that focus much more intensely on exploring C++ and other manifestations of the object-oriented "revolution." (As a grizzled revolutionary, I feel I am entitled to put that word in quotes.)

Despite those endless resources Mr. Ewton refers to, I find few college textbooks or treatises that address the needs of the workaday C programmer the way this magazine does when it's at its best. Just look at the topics covered by letters earlier in this issue.

I believe that we have a broad mission. It's my job to hold the best focus I can by balancing the interests of our diverse readership. If I am too far off the mark, it's Robert Ward's job to educate me or replace me. — pjp