C
Lost in the Company of Giants
It's hard not to take a book like C and compare it to such acclaimed and trusted books as K&R, Expert C Programming, and other lesser known, but equally good tomes. Unfortunately C doesn't really compare with many of the other classic books covering the C language. For starters, the writing in this book isn't quite up to the same caliber as the other books. Part of the problem with this book is language. English does not appear to be the author's native language. There are sentences in this book that require a few glances to glean the full meaning. C is difficult enough to present without a language barrier introducing more problems. Another problem is organization. The ideas presented at the beginning of the book are muddled and disjointed, with multiple ideas introduced but not formally explained until later. Beginners will have a terrible time working through this book without becoming quickly confused, and experienced programmers will likely pass on this book in favor of the other well-known books.
Not All Bad
The book is not all bad, however. The examples in the book are plentiful and are based on tried-and-true examples found in books like K&R. There are some idioms that are used in the examples that will irk the more structured programmers (not using braces in certain areas being the biggest example), but most of the examples are pretty good. Also, the explanations of the more advanced topics are relatively good considering how confusing the more basic material is. Memory management is explained well, with clear diagrams (although the programs are a bit confusing without a careful eye).
So What's in it for Me?
Addison-Wesley is clearly marketing this book to the same crowd that purchases quick-learning books. Unfortunately beginners purchasing this book will quickly find themselves lost amid the confusing descriptions in this book. Those who manage to muddle through will find some tasty bits of information locked inside, but the work involved in getting there outweighs the rewards. Most programmers will probably want to leaf through a copy of this book before purchasing it to make sure they'll get the most out of it.
You can purchase C from Fatbrain. Want to see your own review here? Just read the book review guidelines, then use Slashdot's handy submission form.
If you are reading this discussion because you are planning to learn C, know that not only is K&R's book a very fine book, but there is geek cachet in being able to say "I learned C from Kernighan and Ritchie".
One of my CS profs (Georgia Tech people probably know who I'm referring to) gave the class advice on buying a C book: Flip through the book. If malloc isn't covered, put it back. If malloc is covered in an appendix, put it back. If the book contains the line cp=realloc(cp,n); then "burn it! Burn it right there in the store! Burn all of them!"
Actually, "C" is about dead-on average, I'd say!
markIf you want to make an apple pie from scratch, you must first create the universe. -- Carl Sagan
Learning C as your first language, without any prior computer experience may not be the most clever thing to do. Programming C efficiently, correctly and clearly is best achieved by first understanding computer architecture and programming concepts.
A higher level language provides the abstractions necessary to accommodate "logical thinking" as opposed to a full understanding of say memory management and system I/O. Also, C is quite an orthogonal language in that it supports many awkward combinations of features and constructs. If you are not careful to make your source text clear and readable, debugging even your own code can be oh so cumbersome.
Hence, perhaps reading a book such as "Computer Architecture: A quantitative Approach" by J. Hennessy and D. Paterson is a sensible step towards learning C for the beginner.
The best book for C beginners I've ever come
across is _A Book on C_, by Al Kelley,
and Ira Pohl. I've recommended it to quite a
few beginners and they've all said it was an
easy and very informative read.
"A man talking sense to himself is no madder than a man talking nonsense not to himself."
So what you're saying is that you prefer a language that has NO MEMORY MANAGEMENT to one that does?
A good programmer can manage memory without the help of the runtime environment. There's a certain pride in being able to program with no memory leaks.
Yeah because if you don't buy "Advanced C Programming By Example", then K&R might fall over on the shelf.
"i can never say no to anyone but you"
An old april-fools joke, this snippet will give you a good chuckle at the expense of C:
% 2))P("| "+(*u/4)%2);
"We stopped when we got a clean compile on the following syntax:
for(;P("\n"),R--;P("|"))for(e=C;e--;P("_"+*u++/8)
To think that modern programmers would try to use a language that allowed such a statement was beyond our comprehension!"
Also check out shooting yourself in the foot in various programming languages.
--
Disclaimer: The above statement probably includes half-truths, because real truth is too complicated.
Not only that, but pulling a dog-eared, bookmarked, highlighted copy of K&R off your bookshelf has the panty-removing power of playing your band's seven inches or flashing the keys to your '57 Corvette.
If it ain't broke, you need more software.
Reasons to still use C (at least sometimes):
1. It is the native language to most operating systems API (*nix, MS-*).
2. It is the language most third party librarys and code is written in.
3. It is the language a lot of old code is written in.
4. Interfacing other languages with libraries or APIs written for C is never as easy as the documentation says it is and issues may slow down development time significantly.
5. It is the only widely used standardized all purpose language that is available to all platforms.
C++ - is hardly standardized (most compilers still does not come close to the ANSI-C++ standard).
ADA - Is not widely used.(unfortunately)
Java - Is not an all purpose language.
6. It is a very elegeant and consistent language (unlike C++).
What makes you think dynamic memory management in C is efficent?
Just because "malloc" and "free" each fit on one line of code doesn't mean they are fast or efficient. In particular, if your memory arena gets seriously fragmented, the performance of these routines can get worse and worse over time.
As opposed to a genuine generational garbage collector, for which the performance stays relatively consistent.
Goodness, this is an awfully empty review. Except for the comment about the author's native language (which humorously is followed up by an awkward if not ungrammatical sentence from the reviewer), this whole review could be applied to practically any programming book! What sets this book apart? If nothing, then why review it?
Anyway, the real reason I clicked on this article is because I just love a C debate. Since there's hardly anything to talk about with regard to the review, let's get to it!
Here's what I say: outside of the low-level systems crowd, C should die. We should *not* be teaching beginning programmers C or C++. C should not be the "default language" of computer programming.
Today, efficiency is no longer the primary concern about software. It has been ousted by robustness and ease/cost of development (modularity and reuse). C is awful for robustness (the language lets you "get away" with anything you want, though those things are seldom what you want in application software), and even worse for modularity and re-use. Modern languages, or even quasi-modern languages like Java, are far better than C for robustness and ease of development. They even win on some points which are typically seen as less important than efficiency: portability, elegance, etc.
Finally, the efficiency of high-level languages is comparable (though not as good as) C. Compiler technology is improving somewhat, as well. But since developing and debugging take less time, you have more time to optimize your program (if necessary), so I am not convinced that this is really a big deal. Yet, even if I need to concede the efficiency issue, I still believe modern languages beat C overall.
I'll be glad to argue about that stuff, but today I have a different point to make. C is also holding back the progress of other computer fields. Let me give you an example. My friend is working on compilers that compile high-level languages (to them, C is a high-level language) down to circuits. Here, discovering data parallelism in the code is probably the most difficult problem. Of course, the same issues arise in compiling to architectures like the IA-64 or even P4, where in order to get best execution speed, the compiler needs to figure out what instructions can be executed in parallel.
When they compile C, they need to look for common idioms (certain patterns of for-loop use), then analyze them to extract the parallel algorithm. For instance, this simple C loop adds k to every integer in an array a of size s:
for (int i = 0; i < s; i++) {
a[i] += k;
}
The idea is that the compiler should be able to produce a circuit that does all of the adding in parallel, on silicon. Since you all probably grew up on C, this seems like the totally natural way to write that code. In fact, it is short and it is straightforward. Unfortunately, it is less straightforward to a compiler. The compiler needs to prove to itself that the for loop can be parallelized -- what if the programmer changed k or a or i in the loop body? The C code actually says to run each loop iteration sequentially.
Of course, compiler writers have gotten pretty good at catching this particular idiom, but when the code gets more complicated (especially when the compiler needs to do alias analysis), it is not so good.
The chief problem here is that the programmer is unable to effectively communicate his parallel algorithm to the compiler. The programmer takes something in his mind "add k to all elements in the list", sequentializes it for C "for (int i = 0 ...", and then the compiler has to *undo* this sequentialization to produce the parallel code. In the process of translating, some information is always lost.
Now look how this code would be written in SML (a so-called "modern language"):
Array.modify (fn x => x + k) a
(fn x => x + k) is a function expression (SML lets you pass around functions), and Array.modify simply applies the function to every element in the array. Here, the compiler can very easily tell that my operation is parallel, because I used Array.modify! The code is also a bit shorter, and I also think that this code is a lot clearer. That's subjective, of course. BUT, I hope you will agree that for this example, the SML code is closer to what the programmer means, and easier for the compiler to understand.
Anyway, perhaps some of you will say that this particular issue is not a problem, or that it is already solved (I would like to hear the solution!). I merely mean to propose an example of a theme I have been observing over the past few years in many areas of computer science. Computer programming is about communicationg with the compiler or machine in such a way that it is easy for the human to create code, and easy for the machine to understand it. C was never particularly easy for a human to create (though we have become accustomed to it), and though it was once easy for a compiler to understand, this is becomming less and less true. When the language is neither optimal for humans nor optimal for compilers, doesn't that mean that something needs as change?