Review:The Practice of Programming
This book is written by some heavyweights in the industry: Brian Kernighan and Rob Pike. I have not read previous efforts such as The UNIX Programming Environment or The C Programming Language, but I understand that they are excellent works. I was hoping that this book would live up to that pedigree.
I was not disappointed. The Practice of Programming is a great resource. I found the book to be a good mix of Steve McConnell's Code Complete, Steve Macguire's Writing Solid Code, and Jon Bentley's Programming Pearls: all excellent works in my experience.
Structure
The book offers nine solid chapters devoted to the practice of programming: the tasks that we perform every day to develop software. They range from the beginning of the process (eg, interface design) to the end (eg, testing); from higher-level considerations (eg, portability) to lower-level (eg, naming).
The authors provide examples culled from their real-world experience. I particularly enjoyed their debugging anecdotes, especially their hubris in discussing their own bugs. The authors also provide illustrative exercises, annotated supplementary reading, and an appendix of collected rules. The quality of these is high.
Style
Kernighan and Pike write with facility, clarity, and authority. It is easy to tell that their advice comes from wisdom and experience. I found the text to be readable and enjoyable, and the examples to be relevant and understandable.
The authors' presentation really makes this book valuable. It is neither dry nor difficult to read. In fact, even when they cover difficult material, they are careful to present it in an accessible manner. A college-level programmer should be able to absorb chapter 9, even though the authors build a toy VM with JIT compiler -- not a trivial undertaking.
Examples
The examples in this book really stand out. There are many, almost one per page. The bad examples are appropriately marked with '?' characters, the good examples are nicely commented, and each is concise and typically adapted from real code.
The authors employ many programming languages to illustrate their points. Although they have a distinct bias towards C and Awk, they also present C++, Java, and Perl code, and are careful to use idioms particular to each language.
Often, they will present several versions of the same program. When they do so, they discuss code length, clarity, and related issues, and compare performance, scrupulously noting the environments used.
For example, in chapter 3 they design a single program and implement it in C, Java, C++, Awk, and Perl. In chapter 6, they apply their testing tips to those programs. I appreciate this kind of continuity in a book.
Nitpickings
I have a few nitpicky comments regarding this book. I really don't like the
authors' predilection for short local names, which seem clear in a book's
example but aren't so sensible when being maintained in real-world code. The
world would have been a better place with a compare_strings
function instead of strcmp.
Scott Meyers counsels us (More Effective C++ Item 6) to prefer
preincrement to postincrement, yet the authors continue to use the latter in
loop control statements. The authors also eschew Java's
boolean/false/true in favour of int/0/1; for what
reason, I am not sure.
Still, these are nitpickings. Those issues are relatively minor, somewhat religious, and do not detract from the value of the book.
Summary
I think this is a good book, and I definitely recommend this sort of reading for colleagues of mine. If you've read the books I listed in the overview, then you can get by without this one. However, I feel that it doesn't hurt to be exposed to slightly different presentations of the same material, if only to reinforce the lessons learned.
While I read this book, I was engaged in a coding standards effort in my previous employment. I did find this book, in conjunction with others, to be a useful resource. In particular, I believe it is the most directly applicable book of its sort to development shops that have a lot of C code. That includes the Linux community.
The Practice of Programming is most suited to an intermediate level programmer, although beginning and advanced programmers will also find knowledge in its pages appropriate to their level.
The book's official site contains source code and other resources.
To purchase this book, head over to Amazon and help Slashdot out.
TABLE OF CONTENTS
Preface
Chapter 1: Style
Chapter 2: Algorithms and Data Structures
Chapter 3: Design and Implementation
Chapter 4:
Interfaces
Chapter 5: Debugging
Chapter 6: Testing
Chapter 7:
Performance
Chapter 8: Portability
Chapter 9: Notation
Epilogue
Appendix: Collected Rules
Index
Sure functional programming languages are more expressive, but they are very inefficient. I will believe that it is efficient when there is a practical OS designed in an FP language, till then C or C++ is the only language for us system programmers, maybe Java will catch up some day.
;-).
For the rest of the world probably visual languages will be better than these expressive languages, as they save lots of time, from coding.
I believe that FPLs are forever doomed to be used by the computer scientists, rather than computer engineers.
Probably K&P should have named it The Practice of Programming, by system programmers
"The C Programming Language" is, of course, the "C Bible".
:-).
It is not, IMO, the best way for a C-newbie to approach
learning the language, but it is a must-have. Not because
it's "The Bible", but because it's a good book. "The UNIX
Programming Environment" is an excellent book. I would
not be without it.
Given my experiences with those two books, and the positive
reviews and comments I've seen here, "The Practice of
Programming" will soon join them on my bookshelf.
This article was a day late: I just bought a new load of
books at Border's yesterday! So this one's in my Palm
Pilot's memos for my next trip
I would like to thank SEGV for the nice book review. I'll probably go look for this in the near future. But what I really want to comment on is this quote from the review.
I have not read previous efforts such as The UNIX Programming Environment or The C Programming Language, but I understand that they are excellent works.
Wow, I suddenly feel real old right now. A "few" years ago, all I needed was a few reference books, K&R for C, K&P for sh, and Anderson & Anderson for csh. These were the essentials (there were no books from O'Reilly back then). And forget Programming Style, we just winged it.:)
You speak of "the complexity of modern software". That's where you've gone wrong. It is not inherently complex. People just make it that way, and that's why it sucks.
Not really. "Writing Solid Code" is a very good book --definitly required reading material. The M$ Press label kept me away from it for a long time, but after I read a friend's copy, I ran out and bought my own.
It contains alot of good advise and examples. I don't recall Macguire being pedantic about use of (ugh) Hungarian. All the C-Kiddies who rely on obfuscated tricks could learn alot from this book.
On top of that, I e-mailed him a couple of questions and three days later, he had sent me a very clear and detailed (4-page!) response. That alone put him up a couple notches in my book.
Anonymous Kevin
PS: BTW "Code Complete" is far too large to be a good book. It has snippets, but overall, I've not used it.
Imperfect C is. But its diamonds must far outweigh its stones.
Does C have any diamonds? Maybe some sparkles, but I don't know if they are diamonds. On the positive side:
It is more productive than writing in assembler.
It is relatively easy to write a compiler for.
It is nearly universal.
But the negatives are very hard to ignore:
It is not typesafe.
It doesn't check array access.
It has pointers, a source of constant errors.
It doesn't have automatic memory management.
It doesn't support functional programming.
It doesn't support object-oriented programming.
C was good when it came out, but a lot of advances have been made in programming language design in the 30 years since.
C has had terrific staying-power. And even today shows no sign of
imminently falling into wide-spread disfavor. Given the advances in
the science, I believe that says something about the language.
Windows has staying power too. I don't think popularity or staying power have much direct correlation with how good something is.
Code Complete has been recommended to me many times, but when I've picked it up and gone through it I've never been inspired to get it. The OO issue you brought up is one reason (I'm an avid Pythoneer these days).
:-)
What would be a good book, in the manner of Code Compete, that addresses OO issues as well. Does the Kernigham & Pike book cover some OO issues?
PS. I have Design Patterns already.
that is to say:
int x = 5;
(x != !!x)
demorgan(i think) be damned
That shit is bass ackwards. Its completely moronic.
Perhaps the most humorous thing about it is that its used in C++. The idea of attaching data type information to every variable goes against just about every OO ideal there is that its not even funny.
The idea is to go AWAY from incidental complexity of computers to solve problems, in this case having to declare types and sizes. But once I declare my 'counter' I don't really care what type it is in my algorithm, but NOOO some moronic idiot invents a stupid way to attach the type to every variable name. The whole point is that the type is NOT important information. So you would call it 'nCounter' or 'ncount' either way the fact that you declared this as an integer is completely irrelvant. I hope this practice doesn't take hold anywhere but in MS shops and it dies with MS.
This will cause MS programmers to be forever in a quagmire of stupid programming practices and shitty code. Join them if you wish.
A couple problems with this comment. First, short int require virtually an identical amount of time as 'int'. Also, it will insure that it is using the smallest word size for the computer.
/least/ the smallest word size, which I believe is 1 byte.
/no/ space, and is less likely to be compatible in different compilers.
Nope, it has to be promoted if its to be put into a register that is larger than short. The promotion may be trivial, but its there and the processor must expect it.
Now, about using boolean to save space... You OBVIOUSLY don't know what you're talking about. When the computer allocates a variable, it has to use at
You obviously miss the point here. With the exception of a toy program, you would likely use boolean more than ONCE. So say I want 8, 16, 32 boolean flags, and I'm testing them around the same place in my code (which is very likely). This would take 1 register load, and then 8, 16, or 32 and test's to see if the flag is set or not. With some parallelism 8 or more of these could be tested at once. Now compare this using 8, 16 or 32 integers, each required the same load to register, and each require a similar and test. The drawbacks is of course the hugh increase in loads (memory access is a lot more costly than anything else period) compare 1 to 8, 16 or 32. And also its a lot harder to figure if these can be executed in parallel.
Which is what a short int is. So, when it allocates a boolean type variable, it allocates 8 bits, but only uses 1 bit for actually storing the information, so it saves
As I mentioned above, typically you wouldn't only have 1 bit of information. If you want to look at that as a worst case go ahead but its not based on reality for anything but a toy program. Its not unlikely to have a couple flags in each function, and definately not unlikely to have more than 1 flag in a program. Quite the contrary.
I agree with your opinion wholeheartedly but I find your metaphor, umm, uncomfortable.
Genetic algorithms may be very useful for certain types of problems, and are actually being employed in certain problem domains. I'd say they are still in their infancy, and the research needs to mature. But no one would suggest that the software as it is should be used for civil engineering.
Supposedly, many brokerage firms are now testing and using these algorithms to try to predict the stock market. Those algorithms that do a poor job get killed off, those that do well, are allowed to survive and diversify. The dubiousness of this practice is left for the reader to decide.
What "OO issues" do you mean? You might want to check out Object Oriented Software Construction by Bertrand Meyer. A lot of the book is thinly disguised propaganda for his view of the OO world (i.e. the almost summary dismissal of typeless and dynamically typed languages). It is fairly long however (and expensive). It does, however, provide a way to design/write OO programs.
I also liked Designing Object-Oriented Software by Wirf-Brocks although it was kinda pricey for the amount of content it has. Plus I like CRC cards...other people don't.
Hmm. I'm not positive, but wasn't "Elements
of Programming Style" written before there was C?
The examples in my copy are in Fortran and PL/1
so that's a fairly safe bet.
I would never buy this book because:
1.) It doesn't look very interesting. Looking from the table of contents, I suspect that most of the ideas in the book are rather obvious.
2.) The programming languages they use in the book are the standard ones... which are ho-hum at best. Why not compare some interesting new programming languages?
3.) He unleashed on the world a language with a great number of design flaws. Everyone makes mistakes, but I am not aware of any attempts by him to correct the design flaws in the language.
Choose a language because it efficiently maps onto the problem set. C has proven that
it maps well onto a wide range of problem sets.
C has proven that it DOESN'T map well onto a wide range of problem sets. It is okay for kernel programming, but for application programming it leaves too much to be desired. C programs are several times longer than programs written in higher level (but still efficient) languages. C programs tend to be buggy and unreliable. The C source code I have looked through in some of the standard linux untilies has been pathetic. Really poor quality code. I think a major problem is the use of C. It is very hard to write good code in C because C just does give you the tools to write good code. Sure you can write bad code in any language, but C makes it easier.
Soustrup designed C++ because the language he was using didn't map well.
Stroustrup (sp?) designed a terrible language and should be infamous, not famous.
If people want to get really picky about context, then they would do something like this:
... }
#define STRCMPLESS (-1)
#define STRCMPEQUAL 0
#define STRCMPGREATER 1
...
if (strcmp(strx,stry) == STRCMPEQUAL)) {
-----------
This yields the most readable code, yet may not be the most efficient code. When one is writing for speed and efficiency over readability, then using !strcmp may be the way to go. However, it really depends on which function is optimized better by the compiler: logical inversion (!x), or zero comparison (x == 0).
-- UOZaphod
It probably deserves a 10 only if they change the name to ".. C Programming ..."
The fact that they still prefer ints to booleans shows that they have never really gone beyond the use of C as an assembly language where there are no language abstractions.
AWK was (no, still is a great book).
But "Elements of Programming Style" is a disaster for the the same abstraction reasons. In that book a whole pre-processor is invented in order to turn FORTRAN into C.
The whole world need not (should not!) look like the syntax of C.
I really don't like the authors' predilection for short local names, which seem clear in a book's example but aren't so sensible when being maintained in real-world code. The world would have been a better place with a compare_strings
function instead of strcmp.
How is that relevant to local short names? strcmp is a function so its global, a good name by that style may be compare_strings.
You'll find many of the original standard function names are 6 characters or less, Hmmm I wonder why? And then you'll see stuff like stricmp, or strncmp, odd eh? Wonder why they put the i and n in the middle of strcmp? Good question, all of those things had a reason and its quite beyond too late to change them now. To make the connectin in this paragraph, note that the first 6 characters in all of those string functions are unique.
if ( something == TRUE )
It seems pretty pointless to have the TRUE in there at all. if(something) is perfectly readable to me.
An even worse example:
I used to work in Visual BASIC. We had a custom control which had the property "checked", our code looked like this:
if (not (control.checked))
The problem is that for some reason, the checked property returns "1" for true (VB usually uses -1). Not (1) = -2, also true. It took a while to track this down, and I've always been careful about "true" ever since
Reminds me of Don Knuth's discussion of a robotics algorithm: "The good news is that it is O(n**k), not O(k**n). The bad news it that k is 64."
functional programming is programming without use of assignment or mutable data (according to the wizard book). check out Haskell if you want to know more, as it seems to be the most popular pure functional language. scheme is pretty common among the functional programming scene too although it isn't a functional language (it supports the idiom well though). c would be a horrible environment for functional programming so be thankful the person you replied to didn't design c :) he was kinda strange. who would want garbage collection, no pointers, and functional programming in c?!? i find it amusing that people complain that a system level programming language isn't also a high level language. why not complain about not having garbage collection in assembly or register level access in scheme. makes about as much sense to me
The documentation says 18 characters, but the first six must be unique...
Kewl. Make your code less readable for what?
So you can "die at compile time"? If you are
using any reasonable compiler (gcc comes to mind)
and are compiling at a reasonable warning
level (-Wall, for example) you will also be
reminded at compile time about a bogus assignment
inside a conditional.
You will notice this because you otherwise would
never be so lame as to -want- to make an
assignment inside a conditional, yes?
Show me an 80+-floor skyscraper that isn't evolved.
Sure functional programming languages are more expressive, but they are very inefficient. I will believe that it is efficient when there is a practical OS designed in an FP language, till then C or C++ is the only language for us system programmers, maybe Java will catch up some day.
Two words: Lisp Machines.
I've never understood why people say that. You just have to know what you're doing [with pointers]
Well obviously you are special, and only other people have problems.
Pointer errors are common in C software (even in shipping software). See the Fuzz Revisited paper. The most common programming errors in the standard unix utilities which they tested were pointer errors and array access errors.
Why don't you try the Hungarian Notation. :-).
With a risk of sounding like a Microsoft affectionado I have to say that Hungarian is one of the best inventions of M$. It addresses the scoping problem and quite a few others and gives a consistent guide to variable naming.
Besides the guy that invented Hungarian no longer works for MoneySoft
who would want garbage collection, no pointers, and functional programming
in c?!?
People who want to be productive and not write buggy software. That's who. You seem to be oblivious to the fact that garbage collectors have been written for C. Obviously there is a need. Things are much nicer if GC is built into the language, though, not tacked on as an afterthought.
i find it amusing that people complain that a system level programming
language isn't also a high level language.
Who does system level programming? Not many people. Sure some people hack on the OS internals (the kernel, etc.), but not many compared to the number that write applications.
The worst thing you can do in C is declare a boolean type, or possibly worse:
:)
#define TRUE 1
Why not just:
#define FALSE 0
#define TRUE (!FALSE)
That way it'll work on any compiler
I put this book on order as soon as I heard it was coming out, without even reading any reviews. I just saw who it was by, and said "Yes, I'm getting this book."
It was well worth it. Yes, it almost duplicates stuff found in other software engineering books, but regardless it is still excellent, and very worth the money.
Many people think that Writing Solid Code and Code Complete should be required reading for anyone in the programming industry. If you don't have time to read through the 1000+ pages of those two books, read TPOP.
Besides, most of the languages that are usually considered "better" than C (Scheme, Java, etc.) use run-time interpreters that are usually implemented in C.
That's not true at all. One of the common initial implementation goals of new general purpose programming languages is to bootstrap the language in itself.
I'm confused, I don't understand how using
True/False/ErrorCode(n)/ErrorCode(n+1) gives you anything. In order to get that you need to have true = 0, which is not the case in C. Why don't you just use a boolean variable to represent a boolean condition and pass out-of-band information out-of-band?
Using a true/false bool type limits you to two states. And a flag can only ever be one of two states. What's the problem with that? Unless you aren't talking about flags but rather multistate variables but I wouldn't use a boolean for that in any case. I'd have an enum.
Functional programming? Maybe I should read and review Coplien's Multi-Paradigm Design for C++ next. I understand it is a good book, but have yet to read my copy.
C++ and functional programming don't mix (no matter what kludges someone comes up with).
If you don't to learn a pure functional language, there are some predominantly imperative languages that support functional programming quite well.
> "Different idioms for different languages"
But why different idioms for the same function? strcmp() doesn't return a boolean value even conceptually, it returns one of three int values. You can use "!strcmp" because of the implicit conversion from 0/not-0 to false/true, but it's still misleading. Plus it's natural to read "! strcmp" as "not compare", which is the opposite of its meaning.
Great review. I went and bought the book. I wouldn't mind seeing more reviews of recent books. (Reviews of books that have been around for four or five years are fine, but just not as interesting. Particularly technical books.)
So you advocate something like string.compare() instead of naming coventions that simulate namespaces. Yeah thats great, but str* is C not C++ or Java.
> I suspect that most of the deas in the book are rather obvious.
To you, maybe. And to me, maybe. (I've been designing/coding for
neigh on to 20 years.) But to those with less experience, maybe not so
obvious. I'm going to buy the book anyway. Somehow, even after 20
years, *I* suspect I don't know it all.
> The programming languages they use in the book are the standard
> ones...
That's not a fault, that's an advantage. They're not trying to teach
programming languages, they're trying to illustrate general concepts.
Ways of thinking about and accomplishing things. The methods they
discuss are probably applicable to nearly any programming language.
The fact that they used several throughout the book is indicative of
that. Not to mention that in some cases they illustrated something
with examples in *several* languages.
I think you miss the whole point of the book. (At least as *I*
understand it from the review above.) Maybe you better read it after
all.
> He unleashed on the world a language with a great number of design
> flaws.
IMHO (mindful of the fact that *I* don't know it all), there is no such
thing as a "perfect" programming language. Even when using the right
tool for the job. Imperfect C is. But its diamonds must far outweigh
its stones. At least in the minds of the vast majority of those who
must create things.
C has had terrific staying-power. And even today shows no sign of
imminently falling into wide-spread disfavor. Given the advances in
the science, I believe that says something about the language. And I
don't believe that "momentum" explains it. I believe the facility of
the language for enabling designers to solve problems does.
If I need one, I usually just declare a short int instead, and use it. It's just as fast, uses the same amount of memory, unless I'm confused about the way allocation works, and doesn't require that your compiler know type 'bool'.
Where'd you hear that? The fastest type would be whatever type matches the register size of your computer, which is usually int.
Boolean is good because its only 1 bit of information so with a 32 bit int you can store 32 bits of information, as far as speed, if you are polling this information at one point in a program it would certainly be faster than retrieving 32 seperate integers.
However the fact of the matter is boolean is not a base C type so there is hardly any way this kind of thing is optimized if you were to use it. In C++ maybe.
no text
Jason
"The Elements of Programming Style" predates C -- it was written in the day of FORTRAN and PL/I. I wouldn't call that book a "disaster" just because it failed to predict the future twenty years ago.
The book with the RATFOR -> FORTRAN translator is "Software Tools" by Kernighan and Plauger, published in 1976. RATFOR is not Java, but it's a lot better than FORTRAN.
Arguing language trivia misses the point of The Practice or Programming (and the earlier classics by Kernighan, Plauger, Ritchie, and Pike) -- the value is in their discussion of programming as a process, and some specific techniques that are a more concrete and applicable than patterns.
To say that the authors have "never really gone beyond the use of C" reveals an ignorance of Kernighan and Pike and their work. Kernighan has expressed doubts about the religion of object-oriented programming, and has preferred C to C++, but he has also been a long-time advocate of abstraction, data hiding, and modularity, even when working with languages that have little or no built-in support for any kind of abstraction.
This book deserves a 10. Yes, it contains
subjective opinions, but they are well thought
out. I can't think of a better book on "how to
program."
I enjoy your book reviews and often order the book. It would be useful if /. would include a link to the book at Amazon so we can jump straight over. It doesn't hurt that Amazon will pay /. a small fee for each book purchased in this manner.
That's not a fault, that's an advantage. They're not trying to teach
programming languages, they're trying to illustrate general concepts.
Ways of thinking about and accomplishing things.
The problem is that they only show a very limited way to think about and accomplish things because they use the 'standard' lowest-common-denominator programming languages.
How about showing off the advantages of functional programming?
Or showing how lisp or scheme can be vastly more powerful and flexible than the most popular languages in use today?
While I have not read the text (yet) I would
expect it contains Useful Information that a
a capable reader could seperate from language-specific implentation detail. If not, it should be of the suggested title. If so, it would be a boon to anyone.
Storytime: I do work in Forth (love it, hate it, it pays my bills) and the weirdest stuff I have to deal with is stuff that was 'written like C'. I'm not saying C is bad - I am simply agreeing that what implentation works well in one language may not in another. I'm quite sure that if I applied what I do in Forth to C it would result in a suggestion of psychotherapy at the mildest. (btw, as a general bit of programming philosophy I recommend Leo Brodie's 'Thinking Forth' which despite the title is about programming philosophy rather than how to stuff in Forth...)
And yes, C is spoken here too. Thankfully I arrived after this place had the 'holy war' between languages and it doesn't concern me.
All I seek, in any language, is adequate documentation and consistant style that lends itself to maintainability.
Happy coding.
He's also the editor-in-chief of IEEE Software (a generally excellent magazine). It'll be interesting to see if IEEE Software starts to take on more of shrink-wrapped software perspective or not.
Download, decompress, untar, and then READ:
1. bash sources
2. gdb sources
3. gcc sources
4. gdbm sources
5. etc.
Pick one established, well-hacked, moderately
large gnu system and learn the code.
Your programming will improve like magic.
As someone with 15 years experience (still a kid compared to K&R), I can assure you that experienced programmers *do* need to read and learn throughout their career. Writing K&R C code for a 64k system running DOS 3.1 is *very* different than writing ANSI C90 code for a 4 MB Linux 0.99 system, and that is very different than writing ANSI C9x / C++ code for a 512 MB Linux 2.2 system. As a trivial example, *everything* I learned about memory allocation is now wrong. (Hint: write a memory manager with, and without, a MMU.) My current style would have gotten me fired in the 80's, yet today it screams because I learned how to write code that the VFS/VM subsystem can handle efficiently.
We just seem like we don't learn new tricks because we recognize that most of the "new" tricks are really very old... and are just as flawed today as they were when we first saw them decades ago. Hungarian notation, for instance, is eerily similiar to the early Fortran default typing rules. Bubble sorts were inefficient on slow systems, and they're still inefficient on 500 MHz P-IIIs. The fact that the system is faster doesn't change the fact that a bubble sort may be able to handle 10,000 items... while a qsort could handle 10,000,000 in the same time!
Bottom line: I will read the book, and I haven't seen the inside of a ugrad class for many, many years.
I told Brian Kernighan about this review. Here's his response:
(I'd post my name, but I don't want to name-drop.)Sure functional programming languages are more expressive, but they are very
inefficient.
Not true. In fact, programs written in functional languages sometimes perform better.
Bah, that's just a Geoff Miller line anyway.
It's regretable that no one is working that much on new systems languages these days.
I don't think that's true. There's Sather, Eiffel, Self, Dylan, Cecil. How do you define 'systems languages'?
I don't mean to rain on SEGV's parade or dismiss his talents as a reviewer, but:
Information wants to be beer, or something like that.
Apparently there are a lot of programmers here.
So I just wonder what what you think about using evolutionary algorithms(I know, really heuristics)
to generate code. Danny Hillis said in his book
that this is what he was working on (at least in part).
#1 - Steve McConnell is NOT an employee of MS. He is a consultant that they have used (occasionally to bring their products back on track when they start slipping).
Quite often he also uses his experience from MS as examples of something NOT to do.
Just because he wasn't involved in the development of Unix Or C doesn't mean he isn't a highly capable programmer.
To find out more about him, chekc out his
home page (http://www.construx.com/stevemcc/)
strcmp() et al. come from an older time when external symbols had to be kept unique within the first 6 characters and not case-dependent so the GECOS, 370, etc. UNIX ports could use them.
-- brandon s. allbery, sysadmin @ cmu electrical & computer engineering "Think, youth, THINK!"
Look at the bottom of the article. There are usually big fights in the comments after book reviews between people who don't like Amazon.com and people who do, but for some reason those have slacked off recently.
Kernighan also is (or at least was) executive editor for the Addison Wesley Professional Computing Series, which gave us among other things, the wrintings of W.R.Stevens and several other well known personalities.
strcmp(x,y) == 0 definitely means that the two strings are identical in content and length.
strcmp("abc", "abcde") will return a negative number.
--
Xenu loves you!
I'm no master of obscure C code (I use a reference when I need it, and I much prefer using a small subset of the language), but there is a response at RTFM* to some of the Comp.Lang.C. FAQ's that cites Schildt in C: The Complete Reference as a support, and nothing else.
A sked_Questions_(FAQ) -- but entering in the ASCII codes for parentheses, I still get errors. So go to the directory and get the file :)
Thus my guess would be, if Schildt's books pit him against Comp.Lang.C's FAQ maintainers and contributors, that, well... he needs help.
(*) The filename is Re:_comp.lang.c_Answers_(Abridged)_to_Frequently_
--Matthew
Except that in the cases where they are equal, it would be horrendously inefficient ...
If you want an int return type, use an int. The problem with this multi-purpose return type thing is it's just begging for misinterpretation of the return value.
You would get far fewer errors, I think, with an AreStringsEqual or even a strequ function, rather than using strcmp when all you care about is equivalence.
Ooh, a sarcasm detector. Oh, that's a real useful invention.
The 6-character limit was actually in force this decade. SGI's GL libraries (before X took over the world) had full-length names for C, and 6-character abbrs. for fortran. I assume this was due to language or compiler constraints, not just linker inability...
...but a neat little trick that I saw (and now use) is to rearrange the evaluation order to:
// instead of (iRet == 0)
int iRet = strcmp(x,y);
if (0 == iRet)
blah();
That way, if you happen to accidently type 1 = instead of 2 (==), you die at compile time rather than runtime.
Of course, this is not applicable to the given example (since the function doesn't evaluate to a valid LHS of an =), but I figured Id throw it out there in case someone hadn't seen it before.
Pax -- Ob
Of course, there are many reasonable compilers that don't flag it at any warning level.
I dissagree about readability too. Its a "free" practice adjustment. *shrug* Follow your heart AC.
Pax -- Ob
Assuming that we are dealing with fixed-width characters (which is probably a bad assumption these days), finding the length of a string is O(n), and doing a string compare of 2 strings is O(min(n,m)).
Err... finding the length of a string is trivial, it's simply the number of characters in it. Finding the length of that string's representation on the screen is a somewhat different problem.
Heh. I'm hoping he actually meant Apache...
Obviously, You missed the point of the chapter on style.
In the book they very clearly point out, its not which style you choose(ie variable naming, etc)
but the fact that you choose one and stick with it.
I would suggest you stop pretending to be an "experienced" programmer and go back and read the book. Everyone, *Everyone* has something to learn from this book. For the "experienced" programmers its a good refresher, because everyone strays from the path.
You still don't get it. Too bad.
On a side note:
Why do I care who you are or what you wrote?
I use lots of software everyday, some I wrote, some others have written, and maybe even some you wrote. Just because I may use your code, does make you experienced.
But then again when I think of experienced programmers I think of people who can write "good" code.
BTW: Does benefit mean pisses me off once everyday?? Then I guess I do benefit from your code.
I beg to differ. I think if you take a major application, such as the GIMP (which I've never read the source code), you will find it to be complex.
There's the OS (a complex beast in itself). X above it. Toolkits: gdk, GTK+, etc. Probably some GIMP utility modules. Modules for the graphics. Modules for the UI. Modules for the plugins.
All together, it is complex. Probably it is understandable because it is well designed, by two people. You are correct though that when you are working on a larger project with several teams of 8-10 programmers each, where the architecture has been poorly documented and subverted in cases, that complexity becomes overwhelmingly obvious.
In summary, strcmp is a simple function. It needn't be complex, and shouldn't be. But many software systems in general are quite complex.
--
Marc A. Lepage
Software Developer
I don't see how hard physical constraints would invalidate an otherwise good general guideline. That is, of course there will be special exceptions to the rule and perhaps this is one.
Also, I realize that strcmp is more of a global than a local name. I didn't intend for it to be an example strengthing that specific point I made, only an example of the more general point of naming.
Just today I was helping a colleague at my former employment, where he had gone through my prototype code (excusably imperfect) and changed some (local) variable names to be better named: clearer, longer, more expressive. I have to admit the code was more understandable to myself, who wrote it. That's to say nothing of those who will have to finish implementing it.
--
Marc A. Lepage
Software Developer
I've long suspected that I control the computer book industry, either through my purchases or through my reviews. :-)
Say hi to K. for me.
--
Marc A. Lepage
Software Developer
You are correct, Scott Meyers actually advises on knowing the differences and issues involved. They apply both to writing and to using the operators.
I see several compelling reasons to always prefer pre:
1) it isn't slower
2) it can be faster
3) STL iterators work that way
4) consistency
5) can be argued that it is more semantically correct
In the end, those were just my personal nitpickings and are to be taken with a grain of salt. Others will have different nitpickings.
Actually the K&R style bracing really annoys me and I can't believe I didn't mention that as well...
--
Marc A. Lepage
Software Developer
After writing this review and reflecting on the quality of the book, I went to Chapters and purchased The UNIX Programming Environment, The C Programming Language 2nd ed., and The Awk Programming Language.
I record titles and authors in my Palm Pilot, so I can keep track of what's in stock in Chapters and what the online reviews say. They should have net access in the store.
--
Marc A. Lepage
Software Developer
Exactly, use the idiom to suit the language.
K&P use int in Java code where boolean should be used. That was my beef.
--
Marc A. Lepage
Software Developer
You are correct. For builtin types, which pretty much means all C types, pre and post increment are the same. Although, I have heard it argued that post increment still requires a temporary somewhere, and so still is slightly slower.
But for user defined types, there is a performance hit. Therefore, in the interest of standardizing on one, I prefer that. Also, I find it more semantically appropriate in most cases.
Finally, I believe STL iterators promise the availability of preincrement but not necessarily postincrement. Therefore, consistency with STL iteration would also dictate preincrement.
--
Marc A. Lepage
Software Developer
Well, I am a professional software developer, a rather good one, and I benefited from reading that book. Even after reading Code Complete and Writing Solid Code and other such books. I still benefited somewhat. Imagine if I hadn't read those other books!
--
Marc A. Lepage
Software Developer
Well, YMMV. I don't obey everything in WSC and CC but still found them to be good sources of information.
I actually went out and bought the other K&R and K&P books after dwelling on them. I don't need them to program (I programmed UNIX professionally for 2 years, though likely not at a "hacker" level) but felt they were gospel.
--
Marc A. Lepage
Software Developer
I must agree. Part of the reason I get books like these is so I can share them with others. I didn't mention that in my review, but I photocopied a select section or two for junior developers I was working with. In general I try to convince them to purchase and read the entire book. It only helps me later. :-)
--
Marc A. Lepage
Software Developer
Functional programming?
Maybe I should read and review Coplien's Multi-Paradigm Design for C++ next. I understand it is a good book, but have yet to read my copy.
--
Marc A. Lepage
Software Developer
A boolean that was a byte would be smaller than a short int which was two bytes.
:-)
The oft-overlooked point is that in structures and classes, the compiler may pad and align members to that it takes 2/4/8 bytes anyways, defeating your efforts.
--
Marc A. Lepage
Software Developer
I wouldn't be so quick to absolve older, more experienced programmers. Myself and my younger colleagues have fixed too many of their bugs and design flaws to have that much faith in them, even if they are otherwise quite capable and smart.
--
Marc A. Lepage
Software Developer
Once again, str* as a specific example is in C. But the general principle remains as I have stated it. And in my review, I said only that the world would have been better with compare_string, not strcmp, which is true, in general, not accounting for specific issues such as the linker's limit on characters.
--
Marc A. Lepage
Software Developer
It is published by Microsoft Press, but not written by Microsoft. McConnell is not an employee. Probably Microsoft doesn't follow his advice wholly.
But it is an excellent book. It covers more than Writing Solid Code. It backs up its statements with references to studies and further reading. It is long enough to cover the topic of software construction rather fully.
I've read each of Writing Solid Code, Code Complete, and The Practice of Programming and each is worth reading.
--
Marc A. Lepage
Software Developer
Well, I (personally) review them as I read them. Sometimes I read recent books, and sometimes I read slightly older books. It's not my full-time job (I am a professional programmer) so you get what I read. :-)
--
Marc A. Lepage
Software Developer
I'm curious, how does Pike advocate dealing with the complexity of modern software without layers of abstraction, design patterns, etc.? I may be misinterpreting, can you elaborate on his views?
--
Marc A. Lepage
Software Developer
I understand that reasoning.
But cos is universal in math as cosine. If I went to a non-computer-type and wrote "strcmp" they would be puzzled.
In C++/Java we use namespaces/packages to partition the global namespace, and not naming conventions.
--
Marc A. Lepage
Software Developer
Yes I meant humility. The internal dictionary must have failed me.
--
Marc A. Lepage
Software Developer
The habit of using "!" to not the return of a function will also blow up on you at the oddest times.
Look at the return of the system() call.
C people avoid TRUE/FALSE definitions because it isn't built in. You never know when some goof ball is is going to stomp on your TRUE/FALSE definitions and some people use T/F or TR/FL or other bad things(tm).
--
$you = new YOU;
honk() if $you->love(perl)
GLIB takes a good approach here:
#define FALSE 0 #define TRUE !FALSEIt's still a good idea to not compare to TRUE and FALSE, though, and it's never necessary.
I liked this book. In fact, I was planning to sit down and review it myself next week, I liked it so much.
;-)
'The Practice of Programming' has found itself a spot next to my computer, right next to K&R's 'The C Programming Language, Second Edition'. I think this is one of the best books a programmer could read, especially someone with limited experience.
Ideally, it should be read by all college seniors who are working towards a computer science degree. It is intended for 'younger' programmers, meaning people with fewer than 2-3 years of experience. If you have more than 3 years of programming experience, most of what is covered in this book will likely already be familiar to you. It also does assume a pretty good knowledge of programming over all, so I wouldn't recommend reading this until you've gotten at least a few heavy programming classes under your belt.
Regardless of you skill level though, you don't want to miss this book. The topics it covers include a number of things that are not often well covered, or sometimes not covered at all, in college programming classes. The book picks up where the classes leave off, and gives you a good dose of real world information.
It's kind of like having a mentor at your side, ready to pass on some of his wealth of experience and knowledge. A lot of what is in this book is the type of thing that seems so obvious once you are told, but that you often don't actually pick up for years.
To sum it all up, anyone with less than 3 years of programming experience would benefit greatly from this book. Anyone with more might still want to check it out, as a refresher or even just an interesting read. And personally, I'd like to see it made mandatory reading for seniors in college working towards CS degrees.
Topher
strcmp is also a standard C function... compare_string is not.
Knowing the language doesn't stop at the syntax - you should also make use of the standard libraries, rather than rewriting the same tools all the time.
no taxation without representation!
Using int to represent boolean values is bogus. Yes, it can be used to represent true, false, and error, but that's only valid for languages which don't have a good way of representing errors. The modern languages use exceptions. True or false represents valid return values and an exception is raised for when an error is reached.
This is significantly more sensible than the 0 for false, 1 for true, -1 for error. The code also looks much nicer.
A pity that your mindset is so limited. Code Complete is an excellent book. The fact that it is published by Microsoft is irrelevant.
Hey, you make the world you live in. My comment was in regards to your opinion which was based on speculation and no authoritative experience. I have read Code Complete. You have not. Why not pull back your foreskin of ignorance and apply the wire brush of enlightenment?
What makes the book so great? It's a good collection of techniques that are platform and language independent. It empowers any programmer not so much in terms of completely original material, but as a handy collection of useful tips, tricks, technqiues, methodologies, and so on.
I'm reading TPoP right now and I like it, especially the examples. But I agree with you that they are concentrating on low-level programming, without that much consideration for building larger systems.
...richie - It is a good day to code.
I've got one Schildt book that is damn useful. It's his book on the STL. It's brand new and it covers the ISO standard STL. It's the only readable introduction to the STL that does not start with an assumption that you care deeply about the implementation differences between different sorts of iterators. (yes I care, but not in the middle of a tutorial)
"Thinking in C++" (Bruce Eckel) just confused the heck out of us -- we spent more time disentangeling the code samples than we spent talking about what was actually going on.
But yeah, the Schildt C++ bibles and whatnot are good doorstops.
I recently bought and read this book on the recommendation of a colleague. I quite enjoyed it, and would advise any serious programmer to read it. This book is in the category with other books like Writing Solid Code which are not about languages or algorithms, but about how programming works at a much more abstract level. Even though each chapter in this work covers a specific programming task, the issues that are tackled are lofty things like debugging, automatic code generation, clarity and maintainability. I do have some issues with the cover art. What's with the wiener-dog? As usually, anything by K or R gets props: 10/10.
if (strcmp(x,y) == 0)
Why do you prefer that? What is the difference between all of the following:
if (!strcmp(x,y))
if (strcmp(x,y) == 0)
if ((strcmp(x,y) == 0) == 1)
if (((strcmp(x,y) == 0) == 1) == 1)
I don't do C++, so maybe I am missing something. But I don't think I am. The first one is the idiomatic form.
Short names for "intrinsic" functions are good. It's not just the matter of preferring cos() to math_trig_cosine_angle(). Having all the string functions in the form strXXX() or strXXXX() lets you claim a portion of the namespace for the standard library (I think current C forbids application programs to use externally-scoped names of the form strXXX; perhaps you're allowed to have str_foo, but strfoo is definitely out).
Having compare_strings() would mean you're all over the namespace, and (as others have noted) string_compare() would fail due to the unique first 6 chars rule.
And, of course, common functions should have short names.
2 dashes and a space, or just 2 dashes?
During the first half of last year, while he was working on the book, Pike gave a semester course in Software Engineering at Sydney University. I was lucky enough to be able to attend most of it. It looks like the course was a test-bed for the book - we implemented shaney and wrote a virtual machine with a just-in-time compiler - both examples from the book, many other code snippets come straight from the lecture notes for the course - indeed much of the lecture notes look
like preliminary copies of chapters from the book.
Something that can, perhaps, not be geaned from the book is the "Pike-course-experience". He started the first lecture by holding the previous year's Software Engineering textbook aloft, and loudly proclaiming that it was less than worthless, and that we shouldn't pollute our minds with it. This caused the academics in the audience (which probably included the previous year's lecturer) to gasp, faint and haemorrage. Much of the CompSci faculty attended the lectures - the sight of two rows of Professors, Assistant Professors, Lecturers, Assistant Lecturers, and Tutors nodding sagely at his every word, showing that they, at least, were in complete agreement with Pike, and in fact came to the same conclusions quite independently, is something that will haunt me for the rest of my days. The fact that Pike is perhaps one of the most opinionated men I've met in my life (regardig programming, at least), didn't make the Faculty's life any easier. At one point one of them questioned a Pike-ism with "But Dijkstra said...", and Pike shot him down with "Dijkstra was a brilliant man, but he never compiled a single line of code he wrote...". He had similar biting things to say about C++, the Sparc architecture, Apple computers, EMACS, X-Windows, Java, and others too numerous to mention...
What I carried away from the course was a subtle shift in my conception of programming. Pike is vehemently opposed to all the layers of abstraction and obfuscation we impose on ourselves in software. He had many, many elegant solutions to everyday programming problems, including gems on header files, byte-order in network programs and user interfaces. He has a keen eye for what can and should be done away with, and his coding style and ethos is a pleasure to behold. If I didn't do the course, I'd probably buy the book...
In the case of iterators, though, you usually want to prefer prefix, since it's faster (it doesn't need to make a copy of the iterator, which you then just throw away).
Clearly the reasoning is that users should be able to use either with preference.
DOH! That should read "...without preference."
--JT
Scott Meyers counsels us (More Effective C++ Item 6) to prefer preincrement to postincrement...
Not exactly. What Scott counsels us about postfix and prefix operators is to know the difference, especially that they return different values (including const vs non-const). The only sense in which he counsels a preference is when he says that the postfix operator should be defined in terms of the prefix operator, because these operators are supposed to be exactly the same except for their return values. A fine example of the rock-solid common sense underlying his terrific C++ books.
Besides, he was talking about the writing of operators, as would be required if creating an Abstract Data Type. Nowhere did he say that in using these operators should you prefer one to the other. Quite the opposite, in fact: his advice that postfix should be defined in terms of prefix would ensure that users of the ADTs could use either safely. Clearly the reasoning is that users should be able to use either with preference.
--JT
BTW, I believe that 'Code Complete' is not just published by M$, but that its author is a M$ employee.
I don't have my copy handy, but I believe that it's published by Microsoft Press.
My problem with Code Complete was not with its being a Microsoft product, but that it completely ignored Object-Oriented programming issues. On the other hand, having seen some of the MFC C++ source code, it's probably just as well.
--JT
...on Herb Schildt. I don't find your comments on him inflammatory at all. His books make great doorstops and table levelers, but nothing more.
There are also entire publishing lines not worth ther weight in scrap cellulose... if Sams went out of business tomorrow, I think I'd dance in the street. I've had to deal with too many newbie coders who I've had to help, only to discover they had a Sams book that represented the center of their programming universe.
Just ask yourself that question... would you go to work everyday on the 80th floor of an 'evolved skyscraper'?
Any given sizable base of code is as complex if not moreso. I'll believe that 'evolving' code is a good idea when I see an evolved system perform as well or better than a system written by good designers and programmers.
...that you can't just make a comment on my opinion rather than trolling through the gutter of personal attacks. Why not tell me about what makes 'Code Complete' so special?
And 'it doesn't matter that it's published by M$'?? Using that logic, I shouldn't look askance at a book called 'Love and Compassion for Your Fellow Man' if I noticed it was written by Adolf Hitler.
BTW, I believe that 'Code Complete' is not just published by M$, but that its author is a M$ employee. Therefore, since I haven't knowingly used any of his code, the only measuring stick I have is the M$ code I've seen (uniformly bad to mediocre) or the middling M$ apps I've used. Which is NOT a good basis for a 'coding best practices' rep...
I had a book of his when I was learning C, but I threw it away because so few of the examples would compile. The book was specifically written for the compiler I had, but that shouldn't matter much anyway with most code. I mean, you know, ANSI and all that. I'm reminded of O. S. Card's comments about his generally horrifying experiences editing programming books.
OTOH, I know some sensible people who've liked other Schildt books a lot.
-j
"Christianity neither is, nor ever was a part of the common law." --
for some reason those have slacked off recently.
Maybe they all realized it's a dumb thing to argue about.
-j
"Christianity neither is, nor ever was a part of the common law." --
One of the common initial implementation goals of new general purpose programming languages is to bootstrap the language in itself.
Not if it's interpreted. You sure could write a java compiler in java (in fact it's probably been done) but I don't think you'd want a JVM written in java. I mean, it's turtles all the way down, you know?
Your point is valid, though, as a general observation. It's a good acid test of a language. If you can't write its compiler in it (or if the developers just don't *want* to
A) It's comparable in intent to C. In that case, the comparison is fair, and it damn well better be good for writing compilers. Ada is probably an example if this, right? I tend to think that Pascal is also, but I really don't have any feel for what the original intent of Pascal was. The dialects I've used (all Borland) smelled a lot like C, but with clunky keywords and assignments inexplicably refusing to return values the way any red-blooded expression ought to. Then again, maybe it grew that way in an attempt to compete with C. Um, I guess nobody actually cares one way or the other
B) It's not at all comparable in intent to C. In that case, it's probably excused from the compiler implementation requirement, but it's also meaningless to say it's "better" than C. Perl is an example of this second category. Saying Perl is "better" or "worse" than C is like saying cats are "better" or "worse" than dogs -- not only is it meaningless, but nobody with half a brain gives a rat's ass either way. I mean, what are you going to do about it? Pass laws? Run for congress on the C platform?
-j
"Christianity neither is, nor ever was a part of the common law." --
obviously you are special, and only other people have problems.
Erm . . . I really sounded like a jackass there, didn't I? Sorry. I do think that not enough people are willing to bear in mind that a pointer is a sharp pointy thing that you shouldn't carry when you're running. C is a language that will merrily bite you if you don't keep a close eye on it. (Actually, that was exactly the point that I was replying to, wasn't it?) IMHO people who get hurt with it are probably not looking at it the right way. A different language isn't just a different syntax; it's a different mentality. At any rate, running off the end of an array in basic or whatever is a bug, too.
Obviously, as you point out, people a lot smarter and more experienced than I make these mistakes. It may be that I'm in denial, or merely that I was drunk when I wrote that post
See the Fuzz Revisited paper. The most common programming errors in the standard unix utilities which they tested were pointer errors and array access errors.
I didn't read that, but I remember reading about it, and IIRC GNU utilities came out looking a lot better than most. This was gratifying, because GNU has these coding guidelines somewhere, which (among other things, like their barbaric indenting style
The more I think about it, the more I think I'm just defending C because I like it so much on an emotional level. So, as in all things, YMMV and use what works best for what you use it for.
-j
"Christianity neither is, nor ever was a part of the common law." --
You mean you know of a skyscraper that was completely evolved from scratch? One where wild animals were let loose on a set of raw materials at close to their lowest form, and through almost completely random action, along with natural selection and survival of the fittest, produced a completed building?
Just one? Hell, right across the river in Boston there's a slew of 'em
If you have, I suggest you alert the media.
I think they know already.
-j
"Christianity neither is, nor ever was a part of the common law." --
You would get far fewer errors, I think, with an AreStringsEqual or even a strequ function, rather than using strcmp when all you care about is equivalence.
If that's what yer into, IMHO use C++, which is a cool language for a whole lot of reasons, not just that kinda stuff.
I don't agree with the "far fewer errors" thing, though I certainly never do !strcmp( ). The problem with that isn't that people forget what strcmp( ) does, but rather that it's easy not to notice the !. I think anybody who's been writing C code for more than a month has come to terms with what strcmp( ) does. Some people always put whitespace around ! (except in !=, obviously), and I respect that a lot. In this particular case, though, strcmp( ) == 0 is far harder to miss, and IMHO it expresses the intent better. Since strcmp() does not return a boolean value, IMHO there's no good reason to use a "boolean value" idiom to deal with it. Once you get past the boolean thing, the whole issue melts into air.
Of course, that's just strcmp( ), which we all know and love from infancy onward. Some random function foo( ) that my pothead coworker dreams up is another matter. Still, I have, after all, seen things like that before, and there should certainly be an explanatory comment in the header file.
You can certainly define a macro
#define streq(a,b) (strcmp((a),(b))==0)
. . . but IMHO that kind of syntactic sugar misses the point of c. Next thing you know, you'll be defining even worse things . . .
#define begin {
#define end }
#define then
. . . or, worst of all . . .
#define LPSTR char *
aaaarrrrgggghhhh!
-j
"Christianity neither is, nor ever was a part of the common law." --
Seriously, don't knock evolution. Given ten million years of hard knocks, "all bugs are shallow".
-j
"Christianity neither is, nor ever was a part of the common law." --
On the positive side:
It is more productive than writing in assembler.
It is relatively easy to write a compiler for.
It is nearly universal.
You forgot one: From the user's standpoint, it's an enormously elegant, graceful, pleasant, powerful language. People like it. It's clear and simple, minimal and (for the most part) sufficient. It's a beautiful piece of software.
It is not typesafe.
You mean casts? Hmmm. Yeah, I'll go along with you there. They're good to have, but they're unsafe.
It doesn't check array access.
It doesn't have automatic memory management.
True -- you get to do those jobs
It has pointers, a source of constant errors.
I've never understood why people say that. You just have to know what you're doing, which is a requirement anyway. Anybody who gets "constant errors" with pointers, would probably get constant errors with references or psychic data levelling or anything else.
It doesn't support functional programming.
Well, that's probably true, but since I have NFI what functional programming is, I haven't often felt the absence as a loss
It doesn't support object-oriented programming.
True. There are people who say that you can do OOP in C, but IMHHHO they don't grok OOP. For one example, much of what is implied by inheritance just doesn't translate into C in any way that I can imagine. I don't see a need for OOP in C, though, because we already have OOP in C, a.k.a. C++, which out of the two is my preferred language most days. For some (relatively trivial) uses, I really think C++ is overkill, and for others it's not efficient enough (kernels etc.) -- but day in and day out it's a really damn nice language to program computers with. I like the fact that C has thrived (thriven?) separately from C++. It's cool to have both.
-j
"Christianity neither is, nor ever was a part of the common law." --
I don't mean to rain on SEGV's parade or dismiss his talents as a reviewer, but:
1. Having not read K&R and the UPE, is a major drawback for any reviewer of the newest book: those are classics that are definitely mandatory for any (wannabe) UN*X hacker.
2. To compare a book by the Elders(TM) to books published by Micros~1 Press is sacrilege! And to boot, "Writing Solid Code" is crap distilled. Its tips are either common sense or useless garbage (e.g. Hungarian notation) and it's pretty obvious they don't practice what they preach. Yes, I *have* read it.
This is not meant to be a flame, BTW.
Information wants to be beer, or something like that.
Instead, consider that an "evolved" program can go through many generations very quickly...it doesn't necessarily need 5 million years or anything silly like that.
-Doviende
"The value of a man resides in what he gives,
and not in what he is capable of receiving."
--Albert Einstein
I'll take that with a salt block, thank you.
Code Complete is an excellent book. While it didn't have many great revelations for me (I had been programming professionally for years before reading it), I found it to be full of good wisdom. (Feel free to translate that as 'it agreed with what I had already decided was good programming practice.') It contains lots of good advice on the craft of programming that is not taught in college, and I've handed it to recent grads at work whose code I'm going to have to maintain.
Of course, you are probably right that Microsoft itself doesn't heed its own author's advice ... but that's no reason anyone should deprive themself of this useful reference.
Actually, I've been exposed to just such advice not too long ago. (Well, maybe a year?)
It came in two parts: an anecdote and then the Perl Style Guide. First, I was in a talk with my (now ex-; non-pointy-haired) boss about programming practices. He mentioned an obfuscated piece he'd done one time, using the same variable name on practically every level of execution (global, subroutine, plus various levels of what Perl calls blocks, though he was writing in C). The whole thing worked because he was insanely careful with scope declarations.
It occurred to me then that I should be more careful about scope in my own stuff, though I still see no reason to take it to extremes. :)
About a month after that, I happened to run into the Perl Style Guide, where it advises using variable_names instead of VariableNames, partly because you can then use case to determine the difference between CONSTANT_VARIABLES, Global_Variables and local_variables.
That one really gave me food for thought, and I eventually decided to adopt it. (Which causes its own problems: not only did I have to learn some new variable-naming habits, but now that I've learned them, it starts to flip me out when I see my old code!)
I'll agree that it's rare for someone to change hir mind on aesthetic issues like that, but it does happen.
Kai MacTane: Web developer for hire in San Francisco
Here's a little ditty I like to define in various places when I'm coding. It's short, sweet, and to the point, and fits well in the C idiom.
#define strequ(x,y) (strcmp((x),(y)) == 0)
--Corey
Not only will they not deserve liberty or safety, Mr. Franklin, they will be DENIED both!
I particularly enjoyed their debugging anecdotes, especially their hubris in discussing their own bugs.
That's a rather eccentric use of the word "hubris". I suspect the reviewer might have meant to use "humility." (Hint: they are opposites.)
>there is no such thing as a "perfect" programming language. Even when using the right
>tool for the job. Imperfect C is. But its diamonds must far outweigh its stones.
Complaints about C should be laid at dmr's door, not Kernighan or Pike. Or did he mean AWK, which I think is a Kernighan production?
I'll definitely be checking out this book. Despite comments above, I learned C from K&R (King James ed) and think it the best programming language tutorial I've come across - as distinct from a 'how to program' book, which it isn't.
While we're slagging off programming tutorials, can I put a bad word in for Deitel & Deitel? Only the on the basis of their Java book (which succeeded brilliantly in frightening a relation off programming for life), you understand. But a shocking squandering of previous environmental resources, firmly in the 'sold by weight' category of computer publications.
A depth of though and the clarity that comes from a true mastery of the subject has been the hallmark of the Kernighan, Richie and Pike works I have read in the past. Yeah, after (mmph) years in before the keyboard I expect it won't all be a total surprise, but I will be taken heavily aback if they don't make me think about some things in a radically different way in future. And that's the mark of a really good book.
And no, I won't tell you what it is or who I am, but if you use a web browser you'll catch the hint.
You wouldn't be referring to Netscape, would you? I seem to have heard a thing or two about crufty code in that piece of programming.
Not a flame, just a good-natured jab
FWIW, the posting by Peter Seebach regarding Schildt's book was made on April 1. Also note that Peter Seebach is a well informed authority on C. He posts many informative messages to comp.lang.c and comp.lang.c.moderated. He is also listed in the credits of the C FAQ.
:)
Draw your own conclusions...
DOH!! it's not needed, but would be potentially faster if the
strings are indeed not equal. Can't even read my own code most of the time....
but strcmp() does not mean strequ(). strequ() needs to be..
#define strequ(x,y) ((strlen(x) == strlen(y)) && (strcmp(x,y) == 0))
Where'd you hear that? The fastest type would be whatever type matches the register size of your computer, which is usually int.
/least/ the smallest word size, which I believe is 1 byte. Which is what a short int is. So, when it allocates a boolean type variable, it allocates 8 bits, but only uses 1 bit for actually storing the information, so it saves /no/ space, and is less likely to be compatible in different compilers.
Boolean is good because its only 1 bit of information so with a 32 bit int you can store 32 bits of information, as far as speed, if you are polling this information at one point in a program it would certainly be faster than retrieving 32 seperate integers.
A couple problems with this comment. First, short int require virtually an identical amount of time as 'int'. Also, it will insure that it is using the smallest word size for the computer.
Now, about using boolean to save space... You OBVIOUSLY don't know what you're talking about. When the computer allocates a variable, it has to use at
--
Matthew Walker
My DNA is Y2K compliant
Matthew Walker
http://www.tweeterdiet.com/ - My Diet Tracking Tool
I haven't actually used this book, but it sounds like a good thing. I know that despite the fact that I am fairly set in my ways on a lot of things, I still like to see how other people do their programming, so that I can possibly improve my programming style. I'll definately look into getting a copy of this book, so that I can give it a good look.
As far as short identifiers go, I hate them as well. I like the name to give me a clear idea of what it was intended to do. And it should (preferably) be easy to remember. I can't tell you how many times I've had to go look up those 6 letter function names, so that I could remember which was which.
Someone mentioned something about Boolean in one of their comments. I find that I rarely use a type boolean... If I need one, I usually just declare a short int instead, and use it. It's just as fast, uses the same amount of memory, unless I'm confused about the way allocation works, and doesn't require that your compiler know type 'bool'.
--
Matthew Walker
My DNA is Y2K compliant
Matthew Walker
http://www.tweeterdiet.com/ - My Diet Tracking Tool
Again, in case anyone is interested, there are two excellent critiques of Schildt here. First seebs':
http://www.plethora.net/~seebs/c/c_tcr.html
and (on Schildt's Annotated ANSI C Standard - even worse):
http://www.lysator.liu.se/c/schildt.html
I.
This book uses C and Java and AWK to illustrate many good ideas about programming.
It is NOT a book about C or Java or AWK.
It is about showing how two very experienced programmers think about how they work.
The themes of the book are: Simplicity, Clarity, Generality, Evolution, Interfaces, Automation, and Notation.
You're ready to dismiss some very important thinking about how to write programs that work (and keep on working) because of some religious idea about notations.
If functional programming is so much better than standard languages (which it is, in many ways), then it is all the more impressive to be able to show how to use abstraction and mental flexibility with the less-helpful languages K & P have chosen. I'm sure they would agree with you that FP and scheme are very powerful tools. They also have enough experience to know that there is no one language that is good for all uses. The last chapter is devoted to the implications of that fact, with sections like "Programmable Tools", and "Programs that Write Programs".
If you don't read this book, you won't learn anything. Your loss.
Anyone that takes the time to read it and think about what it says, will learn.
--
busy, busy, busy
Time in evolution is not measured in years, but in generations. An evolutionary software process can go through millions of generations in a day, compared to humans, which take roughly 20 years for each generation.
When I ask intern candidates to implement a strcmp function, I'm suprised how many of them feel that doing a strlen first is required!
Assuming that we are dealing with fixed-width characters (which is probably a bad assumption these days), finding the length of a string is O(n), and doing a string compare of 2 strings is O(min(n,m)).
So in the case where the lengths are equal we have
O(n) + O(n) + O(n), which is just O(n).
Granted, this is 3 times less efficient, but its probably not horrendously bad.
At least, my algortihms teacher probably wouldn't think so. My boss, however, would.
As an aside, there is a tire store around here called Big-O Tires. I wonder if geeks buy tires there?
Please explain why the length comparision is needed here. Are you saying that strcmp compares on a character-class-by-character-class basis, instead of a character-by-character basis?
I was really just trying to illustrate how different requirements call for different coding styles.
Its been a while since I was programming in C...
"The unicode stuff in the latest version is working fabulously well. My russian mafia friends are ecstatic."
> That's a rather eccentric use of the word
> "hubris". I suspect the reviewer might have
> meant to use "humility." (Hint: they are
> opposites.)
I don't know about that; I've coded some truly
amazing bugs in my time... bugs that I am very
proud of. Any shlocky code-monkey can leave a
dangling pointer. It takes *real* talent to hose
up a program in so esoteric a way that debugging
it becomes a challange of mythical proportion.
>:)
The Bolachek Journals
At first I was thinking to write a reply to Joe Mucchiello comment, but then discovered this one and your "mistakes" (IMHO) looks more generic, so here is my view:
Let's take a look at if(!strcmp(a,b)) {}. If we rewrite this example in some fictional pseudo-language it could be written as if not strings_are_comparable(a,b) then ...: which is opposite to the intent of the original C code, that branches into the if block when strings are equal.
Well, that example illustrante some obvious misconception of the original intent. The case with boolean/bool maybe not so obvious, but carries the very same pitfall - what you write is not what others may read!
I believe that programming languages are not only the means for a single programmer to convert his/her thoughts through some intermediate ("and it better be convenient for me!") presentation into a machine instructions. They should be (and they are, some are just better than others) like an ordinary languages be tools/means to convert you ideas into some tangible form, let you come back to these ideas later (understand what was there), improve them, and let others read and understand what is so great in your creation.
Though usages of "restrictive" booleans, or some other language constructs (DBC for instance) may look painful ("I just want my thoughts to appear ASAP as a working beast"), they are invaluably helpful when you program lives through changes, versions, adaptations and additions that others do.
C is an extremely great when you come from assembly programming camp. You are still able to "talk" to your machine in "almost" it's native language, and still accomplish much more and spend your time more productively. But when it comes to something more abstract, more distant from pure hardware then your ability to communicate ideas and design choises without misinterpretation becomes a matter of absolute priority.
Well, those are some unorganized thoughts. I would like to hear your comments folks.
Alex
Its up to 4 this morning!
Wonder if Rob can retire yet?
I can tell you the meaning of life,
I can tell you the meaning of life,
but you have to promise not to laugh.
Indeed this was because many popular old flavors of FORTRAN mandate only the first 6 characters (or perhaps 8) are significant. When I first learned FORTRAN in the 70's it was done that way. So to be compatible with legacy code and compilers FORTRAN symbols must be 6 chars. However, this restriction was relaxed in FORTRAN 77, I believe, and certainly doesn't exist in FORTRAN 90 either.
On the other hand, that isn't why it's called strcmp. That has far more to do with Ken Thompson's love of short, obscure names, such as sed, grep, cd, as well as printf and strcmp (and strcpy). I've never known there to be a linkage restriction on any UNIX I've used beginning in about 1982. But, remember, it was written in 1969. Does anybody know any more about this bit of ancient history?
"I see great things in baseball" - Walt Whitman
Meyers doesn't counsel us to always prefer preincrement to postincrement. His counsel only applies to user-defined types (see page 34 of More Effective C++). I haven't read TPOP, but it's my guess that since the "problem" is with the authors' use of postincrement in loop control statements, Meyers' advice doesn't apply to the code referenced.
Writing Solid Code is only about 250 pages, and a pretty quick read. Code Complete is indeed fat, but has a very high signal/noise ratio.
Big-O is useful mainly when you're talking about how the execution time will grow relative to the size of the problem. True, O(n) + O(n) won't grow any faster than O(n), but it is still twice as long.
"Horrendously bad" is of course relative, and can only be determined after profiling your application. In some cases it won't make a squat of a difference, but in others it could have a significant impact.
Getting off-topic, I know, but it's possible that control was a tri-state control and as such TRUE and FALSE were not the only possible outcomes. For example, the default checkbox control in VB (and presumably VC++) is a tri-state control: instead of TRUE/FALSE outcomes, the outcomes are vbChecked, vbUnchecked and vbGreyed.
-- "I believe the human being and the fish can coexist peacefully." - George W. Bush, 29 September 2000
Linkers are only required to maintain 6 charicters for external references. Just because nearly all modern linkers maintain more does not mean they all do, nor that your code will not be called to run on an old hp (which is the only machine I'm aware of that accually only maintained 6 charicters) I'm always careful that my external references are 6 charicters. Note that this does not mean they are six charicters long, only that the first six charicters are always significant enough.
Maybe this should be in the jargon artical that follows this one...
Any programming language that wasn't designed by God will have flaws; it's inevitable. Besides, most of the languages that are usually considered "better" than C (Scheme, Java, etc.) use run-time interpreters that are usually implemented in C.
TedC
The original intent of Pascal was to teach programming to undergraduate CSci students.
Borland tweaked it quite a bit and turned it into a pretty good C-like systems language.
It's regretable that no one is working that much on new systems languages these days. Most of the interest seems to be with higher level application programming and scripting languages. I think part of the problem is that C is "good enough" -- there isn't any one thing that could be done to make it a really great language, but there are 30 or 40 minor tweaks that that would make it really good (and incompatible with existing code, unfortunately).
TedC
"Pipe dreams" might be a better phrase than "goals".
TedC
A language that can be used to write an operating system or language compiler without dropping down to assembly language too much. A certain amount of asm is probably unavoidable for performance reasons, although good optimizing compilers are getting harder to beat unless you're really an expert asm programmer.
I'll have to look into the five alternatives that you mentioned. I've heard of Eiffel and Dylan, but I thought they were higher level OO languages intended more for application programming that systems programming.
TedC
I do, because I'm resisting the temptation to make up my mind about anything when it comes to programming. I figure that day I do that is the day I start impeding my own progress. Besides, there's nothing worse than working with a progammer who has made up their mind, and I don't want to be hard to work with. :-)
TedC
I would assume they don't use boolean because it is not part of C which is where they are coming from. The worst thing you can do in C is declare a boolean type, or possibly worse:
...
...
#define TRUE 1
Ugh, that is such a bad idea. When I write C++ I prefer to see:
if (strcmp(x,y) == 0)
But when I write C, I prefer:
if (!strcmp(x,y))
Different idioms for different languages. (Of course, in C++ I would use a string class, but that was tangential to my point.)
I'm not saying it is illegal in C++. I knew I should have found a better example. C++ can obfuscate your code in too many ways to add more of them.
That may be the most readable code, but it's also wrong.
strcmp returns a value greater, equal to, or less than zero. It does not return 1, 0, and -1. That means you shouldn't compare the return of strcmp with your STRCMPGREATER or STRCMPLESS.
This allows strcmp to be implemented in a very simple and efficient way.
I have always enjoyed Kernighans style (and Ritchies to obviously) I have the elements of programming style on my desktop, and reckon its really useful even if I have to translate the points made from PL/1 and fortran (I can't remember which they use) to C(++) and Perl.
I have to point out that using an int as a Flag or True/False allows you to do 2 extra things -
1 it can be used as a simple semaphore which is always handy and still preserves the true/false testing by having a 0 or not 0 state
2 it can be used as True/False/ErrorCode(n)/ErrorCode(n+1)
and again preserve the testing by having a 1 or not 1 state
The flag could also be used to return an int value as a result and maintain state in the same way as a semaphore.
Using a true/false bool type limits it really badly.
Aaron
Intranet/Internet Developer & Linux Advocate
I had NO idea I was addressing a bodhisattva of coding wisdom... perhaps I should ditch my job, give away my belongs and follow you barefoot for the next decade...
On the other hand, your attitude indicates that while you may (again, MAY) be 'enlightened', maybe you're such a pain in the a$$ to work with that you have little opportunity to share your knowledge with others.
Before knocking the 'world' others live in, why not check out your own? Yours seems to be full of road signs that indicate that only *you* know the right way... or better still, join the real world that the rest of us poor stiffs have to live in... you might find it refreshing.
I haven't read 'Code Complete' before, so take this with a grain of salt. If I were going to buy a 'coding best practices' book it would be most likely this one, simply because Kernighan and Pike are the authors. These are two guys who have been writing solid (and in many cases, revolutionary) code for DECADES now.
On the other hand, I never heard of the guy who wrote 'Code Complete' before the book came out. And (warning: anti-Mickeysludge diatribe follows) from the several unpleasant times I've actually seen M$ code before there may not be a SINGLE PRODUCT from M$ written with any of the techniques 'Code Complete' advocates.
*Programmer to Customer* 'Yep, Mr. Smith, using our nifty new evolutionary software engineering process, we can produce a program that works FABULOUSLY... and we can deliver it in a mere 1.5 million years...'
If you're going ot be dealing with normal, human timeframes, evolutionary programming is unlikely to deliver the goods. This is the reason why bridges and buildings are designed and built by people, rather than letting a few packs of chimps loose in a forest full of hardwoods and saying 'we'll be back for our structure in a few eons...'.
You mean you know of a skyscraper that was completely evolved from scratch? One where wild animals were let loose on a set of raw materials at close to their lowest form, and through almost completely random action, along with natural selection and survival of the fittest, produced a completed building?
If you have, I suggest you alert the media. Otherwise, I think what you mean is that the designers and builders tweaked things as it went along. that's completely different from what people mean by 'evolutionary' programming.
Choose a language because it efficiently maps onto the problem set. C has proven that it maps well onto a wide range of problem sets.
Soustrup designed C++ because the language he was using didn't map well. That's a good reason to switch languages.
You should never pick a language because it is "new" or even because it is "interesting", but because it does a good job with the problem at hand.
I imagine that was a very illuminating and entertaining course. I've only seen Pike in person a couple of times at a Usenix sometime in the previous decade. Among other things, he delivered a paper wearing harem pants (him, not the paper).
-- Alastair
If you try something like: if (a == TRUE)
it maps to: if (a == !0)
which means if (a == 1) NOT if (a != 0)
so non-1 values of a will still fail this test.
Bottom Line: Don't test against TRUE/FALSE no matter how they are defined
From reading the other comments here, it seems that several readers agree that this book isn't truly necessary if you've already "been around the block", so to speak. That may be true.
However, I am still seriously considering getting this book so that when people ask me "what's a good book on programming", I can reach over to my shelf and grab a good book before they accidentally pick up the latest boat-anchor by some dubious author such as Herbert Schildt* or the like. All too often, people buy books based on size or weight, and not on the solidity of the content. (Even K&R2's latest reprinting is twice as thick as the one I bought, but with the same number of pages.)
If you're a good, professional coder in any reasonable organization, you will eventually be asked to mentor, tutor, or otherwise assist less-experienced programmers. Make sure you can make the best of the opportunity by having appropriate resources ready.
(*Note: I realize that my comments regarding Schildt might be slightly inflammatory to some, but they're not without some forethought. See the comp.lang.c FAQ for more information. And no, I don't let the FAQs think for me -- I've actually seen Schildt's work and found it atrocious. I reference the FAQ since it points out most of the same things I would and more.)
--Joe--
Program Intellivision!
I found this book to be useful, but if you're a halfway experienced programmer, I think you will have dealt with all of these issues and settled on solutions that you are satisfied with.
Everyone has an opinion on variable names, but once you've made up your mind, do you really care how someone else deals with them? Would any advice make you change? This is the sort of thing I am talking about.
This is a good book for someone to look at after completing a few undergrad courses (when they only know enough to be dangerous, and could use the "realignment").
For more experienced programmers, I don't see too much of use.
Just when I'm having fun reading constructive discussion in here, I come across crap like
I would suggest you stop pretending to be an "experienced" programmer and go back and read the book.
Oh Chad, you don't know how many times (a day, perhaps) you benefit from my programming. How droll. And no, I won't tell you what it is or who I am, but if you use a web browser you'll catch the hint.