Malcolm McLean said:
Next error: Schild writes printf("%f", sizeof(int)) and printf("%d",
sizeof(int));
The first is indisputably a real error. Without a copy of the book we
can't tell whether it is glitch - the cast somehow missed - or a more
serious error. The second is an error because of the vandalism wreaked
on the C language by size_t. The proposed fix printf("%lu", (unsigned
long) sizeof(int)) would be very confusing to beginners. However we do
have the first real errata entry.
This same error occurs 6 times. At no point does the code from the
book show the beginner how to print a size correctly. The problem
isn't the one error as listed on Seebs's page, but that the book never
seems to tell the reader what they need to know. Sure, gloss over it
early on (though I'd not gloss over it like this) but at some stage
the correct way to print a size_t should be in a "complete reference"
to C.
(Somewhere in the 4the edition it must do so because the author will
have to describe the new printf format letters. No examples appear in
collected code, though.)
Next error - sizeof() an array that is passed as a parameter. A real
error. This is a confusing and inconsistent backwater of C syntax,
however it is a real error and it should be picked up.
If the book is a reference (as per the title) then "inconsistent
backwaters" have to be included. If it is a tutorial for beginners
(as you claim) why is this experienced writer including examples that
use "inconsistent backwaters" of the language? It is either an error
of fact or an error of style.
Next error - "This shorthand [presumably +=, -=,*-, /=, %=, &= etc]
works for all the binary operators". Technically the structure member
operator is a binary operator, as are logical &&. So Schildt's
sentence is literally incorrect. However we don't use natural language
in that very qualified, literal sense. Not a real error.
What, I wonder, is a "real" error -- do you mean that you don't
consider it significant? I don't think it is all that significant
either except that it so easy to avoid. "This shorthand works for
many of the binary operators" or "this shorthand works for all the
arithmetic and bitwise binary operators" would both work, or the
author could simply state the combinations that are permitted.
There are more binary operators than more critics have mentioned.
This statement calls into question the meaning of >= and <= (which now
appear to be assignments) and is posits the existence of ===, !==, >==
and <== which don't exist.
Next error: a variable referenced when scanf() fails. I don't have a
copy of the book. However whilst the result is undefined behaviour, in
practice what will always happen is that a calculations is made with a
garbage value. A real error, but not a serious one.
Except that, in what you call a tutorial, it is repeated time and time
again. I don't think there is a single example that tests the return
form scanf, fscanf or sscanf in the whole book. What a shame that
this tutorial never suggests the useful idiom:
if (scanf("what I want", &where, ...) == number_of_items) {
/* do stuff with my data... */
}
Next error: Schildt uses the terms "stack" and "heap". To be ultra-
correct, of course, we should talk of automatic and dynamic memory, or
whatever the C term is for the malloc() pool, I've forgotten myself.
But this is a classic case of demanding definitions where the author
intends to give an explanation.
So OK, there are a few real errors in Schildt's book which the webpage
picks up. But the rate of real errors to errors created by an
insistence on over-literal interpretations, and the rejection of any
type of simplification for the purposes of readability, isn't very
high. Only one error (the sizeof a parameter) so far is both
unambigiously real and presented in a manner that is fair to Schildt,
and the scanf() error is also real. We're up to page 131 and we've
found one glitchy page where everything seems to be going wrong with
sizeof(), and one minor bug in the use of scanf(). That doesn't seem
to me a particuarly bad error rate for a programming book.
I've commented on you comments just because I take a different view.
I fact I think this to-and-fro over the points in one commentary is
futile and not, ultimately, important.
Focusing on Seeb's web page misses the point. I, too, have not read
the book, but the code is on-line and the examples don't show C being
used well and wisely. This is a great shame in a popular book and is
(to my mind) far more significant than the details pointed out in the
error list. One can argue endlessly if such and such a detail is a
"real error" or not, but i don't think anyone who knows C can argue
the book presents C as it should be written.
There are 92 examples of using gets and quite a few examples of
unconstrained %s input formats. There are no examples of using the
return from scanf (and friends). And then there are some of the most
convoluted input loops I've seem since I stopped marking first year
students' work[1]. printf(s) (or the equivalent) occurs often. Not
every example is dangerous of course, but some are. Why get this
anti-pattern into your reader's heads when there is not need to?
In an error list, you can claim that reading into a char and then
testing it against EOF is a detail, but when that incorrect idiom is
repeated several times the reader will surely come to think that it is
correct and "how things should be done". Learners need to be told why
you read into a int, and not doing so at any point[2] is not a
simplification for the purposes of a smooth presentation of the
material -- it is a disservice to your readers.
If the author keeps passing one (or two) less than the size of the
array to fgets, readers will assume that you /need/ to do this. If
the text explains that you don't have to do this, then readers will be
puzzled by the examples that do. The best (simple) idiom for using
fgets with an array is
if (fgets(buf, sizeof buf, fp)) /* ... use it */
but that is never illustrated. Magic number sizes are used instead
and often odd ones to boot.
size_t values and objects are repeatedly treated as if they were ints.
You may disapprove of size_t, but someone learning C needs to know
what it is and how to use it correctly. Using strlen(s)-1 without
testing for empty strings and printing size_t values using %d (ten
times at least) just gives the confused idea that string lengths and
object sizes are ints when they are not. Learners deserve good,
clear, correct examples of how use these types, functions and
operators correctly.
Please, read the code (nearly 10,000 lines of it) and then report
back. I would be very surprised if you think that it presents
beginners in C with good, clear, correct examples of how to use the
language? That should be the real issue -- not whether this or that
error is a real error, a trivial error, or a serious error.
[1] For example:
char ch;
/* snip */
while(!feof(in)) {
ch = getc(in);
if(!feof(in)) putc(ch, out);
}
or:
while(!feof(fp)) {
fgets(str, 79, fp);
printf(str);
}
or:
char c;
/* snip */
do {
ch = getc(in);
/* snip */
if(ch=='\t') {
/* snip */
}
else {
putc(ch, out);
/* snip */
}
} while(!feof(in));
or:
while(*str) if(!ferror(fp)) fputc(*str++, fp);
or:
while(!feof(fp)) putchar(getc(fp));
[2] It may be explained in the test but if it is, why is it not there
in the code examples?