It takes a lot of work to properly criticise an entire reference, but I'll list a few points from version #2 of the reference:
scanf is used continuously without consideration for its return value. Many examples presented in that reference will cause undefined behaviour when given undesirable input, as uninitialised automatic objects are assumed to be assigned values by scanf. This bad habit is introduced in section 2.6 and used throughout the reference.
To comment more on I/O-related errors, consider the code from section 7.3 (length.c):
Code:
#include <stdio.h>
int main(void)
{
int len = 0;
printf("Enter a message: ");
while (getchar() != '\n')
len++;
printf("Your message was %d character(s) long.\n", len);
return 0;
}
- With an interactive device, the desired effect of having "Enter a message: " pop up may not be achieved if stdout is line buffered. A call to fflush is necessary.
- The return value of getchar is not checked for EOF or handled appropriately. That code could fall into an infinite loop.
- Although it isn't all that significant and a fairly unlikely event, len can overflow. An unsigned type would have been a better choice.
That scanf thing was the first thing I noticed. If I flip through at random and see what else I can find ...
From section 10.5:
Code:
int i ;
void f(int i)
{
i = 1;
}
void g(void)
{
int i = 2;
...
...
- In Declaration 2, i is a parameter with block scope.
- In Declaration 3, i is an automatic variable with block scope.
...
- In Declaration 2 the identifier, i, has function prototype scope and the object associated with that identifier has automatic storage duration.
- In Declaration 3 the identifier, i, has block scope and the object associated with that identifier has automatic storage duration.
From section 12.1:
Performing arithmetic on a pointer that doesn't point to an array element
causes undefined behaviour. Furthermore, the effect of subtracting one pointer
from another is undefined unless both point to elements of the same
array.
This isn't true since it's perfectly fine to point at the end of an array.
In section 23.5 he passes chars to the ctype functions without a cast to unsigned char. Scary stuff!
There are surely more mistakes in this book but I haven't really analysed it thoroughly. I looked at one of the versions of Let Us C and it seemed really horrible. I think it mixed C with all of this DOS stuff as well in the later chapters, so to me it seemed a lot worse than this one.
My opinion is that all the C references I've seen are all horrible, but some are less horrible than others. I think K&R2 is the least horrible of the ones I've seen and its main benefits are that it uses very precise language and has a good set of exercises; it's good at teaching the basics of the C language and that's really it. If you want a book on computer programming you should probably look at SICP, for algorithms TAOCP, for the specifics of C the standard documents and c-faq.com, and for using C in practice TPOP. Then there are many other specialised subjects like writing compilers, using networks or graphics, using certain libraries, etc. that none of the references listed above really cover at all, so for a beginner who's learning programming and starting with C, there isn't really one reference that will give them all the information they need.