Computing Reviews
Today's Issue Hot Topics Search Browse Recommended My Account Log In
Review Help
Search
C: a software engineering approach
Darnell P., Margolis P., Springer-Verlag New York, Inc., New York, NY, 1991. Type: Book (9780387973890)
Date Reviewed: Dec 1 1991

I was intrigued by the title of this book. I immediately turned to the table of contents to see how a software engineering approach to learning a programming language might differ from the approaches found in other books. I failed to see any difference. The final chapter, named “Software Engineering,” appears to be the only justification for using the term in the book title. That does not mean that I disliked the book. It provides a highly readable yet authoritative introduction to the C language. Every feature of the C language and the C preprocessor is described simply and by means of well-chosen examples. I am impressed by the writing style and by the thought that has been given to presenting the material in a visually pleasing manner. I particularly like the “Bug Alert” boxes that are interspersed throughout the narrative. Each box describes a common C programming error (the kind where the compiler is unlikely to issue an error or warning message) and how to write your program to reduce the chance of making such an error. The errors I repeatedly make in my own C programs are all covered, as are many others that had never occurred to me but would be troublesome to anybody who hit one.

The authors follow a conventional structure for explaining a programming language. The first two chapters provide a brief history of the C language and give an overview of the structure of a C program. The subsequent chapters give a bottom-up treatment of the language constructs and facilities, beginning with simple datatypes and progressing logically to a chapter on the standard library functions for input-output. The final chapter provides a rather bland discussion of some software engineering principles and introduces an example of a large C program. Appendix A provides summary descriptions of the ANSI C runtime library functions and macros. These descriptions are an order of magnitude more readable than those provided in the ANSI standard document. Appendix D provides a useful summary of the differences between ANSI C and Kernighan and Ritchie (K&R) C.

The book makes a valiant effort to cover both the original K&R C dialect and the newer ANSI C dialect. The dual coverage comes at a price, however. For the most part, the main narrative sticks to C features that are common to both dialects. Features that are peculiar to one dialect or the other are described in separate boxes labelled “ANSI C Feature” or “K&R Feature.” The attempt to provide dual coverage means that all programming examples use the old K&R style of function declaration. For example, page 169 contains the declaration  “void clr (p) long *p; {…”  whereas, using the newer and better ANSI C syntax, this would be written as  “void clr (long *p) {…”  To maintain backward compatibility with old C code, the ANSI C standard does permit both syntaxes, so the book is correct. The standard describes the old syntax as obsolescent, however, implying that it will be dropped from the standard in the future. It is a pity that this book will help perpetuate use of the old syntax. Programmers who use the old syntax risk losing the benefit of having the compiler check that functions are called with the correct types for the arguments.

Even though the book covers both K&R and ANSI C, the coverage of standard libraries and standard “.h” files is based almost exclusively on the ANSI standard. I would have preferred the authors to simply relegate K&R C to an appendix and concentrate entirely on ANSI C. Many C novices will only be confused by the references to the two dialects.

I examined the book carefully and did not find a single factual error. The worst error that I could find appeared on page 145, where the authors say that (unsigned) −5 >> 2 evaluates to 2!#-1 (sic) on a machine with 16-bit integers. This appears to be the result of an accident with the shift key and presumably should read 213−1.

My biggest gripes about the book have to do with the example program provided as an illustration of software engineering principles in action, an interpreter for a subset of the C language. The program uses recursive descent to parse and execute C source code interpretively. From a software engineering point of view, this was a poor design decision. Recursive descent causes the semantic processing logic to be inextricably intermingled with the syntactic recognition logic, instead of being cleanly separated as it would be if a parser generator like yacc had been used. Thus the reader has considerably larger function definitions to read and understand. Maintainability, a goal of good software engineering, suffers from this design. Another consequence is that the prospects of enhancing the interpreter to handle the entire C language are poor--the recursive descent method is not up to the task of analyzing the full C syntax.

Another principle of software engineering is that code should be robust. For example, if fixed-size arrays are used to accumulate lists of values, the code should always check that the arrays are not overflowed. The example program appears to have no array bound checking. Consequently, a long identifier will overflow a text buffer, and a function call with more than 32 arguments will overflow an argument stack. While such coding practice is unfortunately typical of C code in general (in the misguided belief that efficiency is more important than obtaining correct answers), it has to be deplored in a book that claims to be teaching a software engineering approach.

Finally, the example program uses C trickery that adversely affects the portability of the code. (Ironically, portability is another element of good programming style listed in the chapter on software engineering.) The trick that upset me is concerned with the declaration of a data type for describing lexical elements of the C language. The declaration used in the program reads, in part, as follows.

typedef enum lex_vals {LEX_NULL, SYMBOL, CONSTANT, BUILTIN_FUNCTION, RETURN, IF, ELSE, FOR, SWITCH, WHILE= ‘a’, STATIC, EXTERN,…} LEX_TOKEN;

Later in the program, however, the following occurs:

LEX_TOKEN token;

token = lex(&v);

if ((int)token == `*’)…

What is going on here? The program’s author is using variables of type LEX_TOKEN to hold character values such as “*” and “+,” using the cast operator (here and elsewhere in the program) to defeat the C type system. While the ANSI standard indicates that enumeration types are implemented as integers and permits conversions between the two (and therefore between character values and enumeration types), the code is not portable. It assumes, for example, that the internal value for the character “*” is distinct from the integer used to represent the enumeration constant SWITCH. The trick will indeed work when the ASCII coding scheme is used for characters but, unless and until ASCII codes become an integral part of the ANSI C standard, we cannot be sure that it will work on every system. Apart from reducing the portability of the code, tricks like this only make the code harder to understand and tend to inculcate poor programming practices in novice programmers.

On the whole, I like the book, but it would have been better if chapter 12 and Appendix F, the programming example, had been omitted. With these reservations, I recommend it for teaching oneself ANSI C or as an adjunct text in a software course using ANSI C.

Reviewer:  R. Nigel Horspool Review #: CR115070
Bookmark and Share
 
C (D.3.2 ... )
 
Would you recommend this review?
yes
no
Other reviews under "C": Date
C (2nd ed.)
Schildt H., Osborne/McGraw-Hill, Berkeley, CA, 1990. Type: Book (9780078815386)
Jan 1 1992
C for programmers
Ammeraal L., John Wiley & Sons, Inc., New York, NY, 1991. Type: Book (9780471928515)
Dec 1 1991
ANSI C made easy
Schildt H., Osborne/McGraw-Hill, Berkeley, CA, 1989. Type: Book (9780078815003)
Jan 1 1992
more...

E-Mail This Printer-Friendly
Send Your Comments
Contact Us
Reproduction in whole or in part without permission is prohibited.   Copyright 1999-2024 ThinkLoud®
Terms of Use
| Privacy Policy