Isn't "assert(line != NULL && longest != NULL && "memory error");" a bug in Zed's example code?
I think you're mentally substituting "&&" with "||", in which case the assert would never fail because the string "memory error" is never 0. But with &&, the assert will fail when it should and the "memory error" is just a superfluous comment, not a bug.
Deconstructing "K&R C"
111–120 of 136 posts
Re: Deconstructing "K&R C"
#112Earlier quoted context omitted.
It's a nice strawman, right? Especially when he points out that the original code, in context, is perfectly fine. His later complaint about the assignment-in-if statement is certainly something shared by modern C programmers (see compiler warnings about same), but it perfectly fits the original style and accomplishes its task. His criticisms seem to be rooted so far in stylistic issues and in taking the code out of c…
My criticisms are only partially stylistic, but also that people copy this code to other situations and it breaks. So, I'm showing them why it only works in that one specific context and how to break the code.
Please encourage the use of the "restrict" keyword to encourage proper aliasing optimization by compilers.
Also, would it be worth considering, perhaps in a chapter on how-to-deal-with-C-style-strings-if-you-must, including a section on writing compiler-independent macros to emulate safer calls like the str*_s variants in VS. These functions are usually slightly-different in incantation across VS and GCC, so it might be helpful to abstract them. It also is a relatively simple exercise in preprocessor macros with a clear benefit.
Re: Deconstructing "K&R C"
#113Earlier quoted context omitted.
The string data type in the db? Because Redis itself uses char-stars all over the place, with the libc string functions.
Hmm, reading the source it looks like he is using His sds string library, which has Len, size and a asciiz char* member. When last I checked he does pass the char* around (because it is null terminated) but he also sometimes will do pointer math to get back to the sds
Re: Deconstructing "K&R C"
#114Earlier quoted context omitted.
Noble goal, but the way the chapter is written doesn't really come across that way, in my opinion.
Speaking as someone who doesn't know C, hasn't read K&R, but who (usually!) has decent reading comprehension, it _does_ come across this way. He's completely explicit about what he's doing and why. I don't understand how people can read that and still feel that he's being unfair. Maybe I'm just too literal-minded.
Re: Deconstructing "K&R C"
#115Earlier quoted context omitted.
Dated, buggy, and un-stylish examples are exactly what diminishes it.
And those dated, buggy, and unstylish examples would be?
Dated: the "Hello world" on page 6 produces warnings when compiled "> gcc -ansi -o hello hello.c -Wall" c.f. http://c-faq.com/ansi/maindecl.html
Buggy but only to a pedant with infinite time: the word count on page 18 that uses a `double` which will run out of accuracy once you count more words than there are atoms in the universe. ( `double toot = 1000000000000000000; toot++;` what is the approximate value of toot?)
Buggy by omission: Section 5.5 (on page 104) doesn't really go into the hazards of C strings, and the text's implementation of strcpy when using strings from unfriendly places (public wifi, quicktime files) can turn the interesting kind of nasty if you hammer on it enough.
Unstylish: brace-less if statements in many examples; a two-line one on page 110, for example.
I worked as a contractor in a C shop for several months a few years back, and I kind of see what happens when you code K&R-style instead of extremely defensively and conservatively. For example, the strcpy on page 106 is cute, but is it going to be as maintainable as the naïve version the previous page, or the hypothetical (unless I just failed to find it) LCTHW known-length string copy function?
Re: Deconstructing "K&R C"
#116Earlier quoted context omitted.
Speaking as someone who doesn't know C, hasn't read K&R, but who (usually!) has decent reading comprehension, it _does_ come across this way. He's completely explicit about what he's doing and why. I don't understand how people can read that and still feel that he's being unfair. Maybe I'm just too literal-minded.
Calling string manipulation functions buggy and broken because they fail when you don't pass them a string is both wrong and silly.
Re: Deconstructing "K&R C"
#117Earlier quoted context omitted.
I'm probably the last person in the world to prefer: while ((len = getline(line, MAXLINE)) > 0) if (len > max) { max = len; copy(longest, line); } if (max > 0) /* there was a line */ printf("%s", longest); I fear this may be literally true: this brace style is called Whitesmith's, and I was reporting bugs to the cc-mode indenter for emacs a while ago. BSD/Allman and K&R styles never made sense to me.
Add a new statement to the while-loop. Now you've figured out why that style isn't so hot. You now have to remember to go add the new braces, and typically people are mentally putting them in so they forget. Same with the last if-statement. You'll go, add the new line, indent and go "cool done". Then scratch your head for hours wondering why it's not working.
Weird contrast: Perl, for all its klugy syntax, requires fully bracketed syntax on the statement bodies of "if", "while" & the like, so this never happens. Of course, you get other readability issues there...
Re: Deconstructing "K&R C"
#118Earlier quoted context omitted.
It's way worse than an extra byte, or the offset of 1 byte for pointers; it also means you need a whole copy of every substring with its own length delimiter, and can't tokenize in place. C code gets into just as much trouble with length-delimited data structures as it does with ASCIIZ; ASCIIZ is a red herring. People have declared over and over again that it's the single worst decision in C and the cause of every bu…
I partially agree with you, but in a different way. I feel that the real problem is the OS doesn't give code access to its own internal accounting of allocated memory. It already knows the size of any heap chunk you make, so why can't we ask it? In most C code we're carrying around either a null terminator (which can get clobbered) or a whole integer for the size. Instead, there should be a way to ask the OS "how big…
Re: Deconstructing "K&R C"
#119Earlier quoted context omitted.
"Yes, there are problems with the whole approach of using a terminating value" And, of course, there are problems with the other approaches too. Using a single length byte at the beginning limits you to 255 characters and makes pointer manipulation less straightforward (since the actual data starts one byte further on). Using more than one byte for the string length wastes space (a serious issue at the time C was dev…
It's way worse than an extra byte, or the offset of 1 byte for pointers; it also means you need a whole copy of every substring with its own length delimiter, and can't tokenize in place. C code gets into just as much trouble with length-delimited data structures as it does with ASCIIZ; ASCIIZ is a red herring. People have declared over and over again that it's the single worst decision in C and the cause of every bu…
Re: Deconstructing "K&R C"
#120Earlier quoted context omitted.
And those dated, buggy, and unstylish examples would be?
I dug out my 29th printing copy for this :) Dated: the "Hello world" on page 6 produces warnings when compiled "> gcc -ansi -o hello hello.c -Wall" c.f. http://c-faq.com/ansi/maindecl.html Buggy but only to a pedant with infinite time: the word count on page 18 that uses a `double` which will run out of accuracy once you count more words than there are atoms in the universe. ( `double toot = 1000000000000000000; toot…
2. First the nit misses the spirit of the example which is simply to demonstrate that "double" has higher precision than the fixnum "long" type; second, calling it a bug misses the fact that text explicitly does not say you can use it to count arbitrary strings; as the text says, it depends.
3. You're calling "buggy by omission" an implementation of strcpy not substantially different from BSD's libc. K&R's is, in fact, how you would write strcpy(). That strcpy() doesn't handle hostile strings is irrelevant; you're not intended use strcpy() on hostile strings.
4. Hard to fathom how one criticizes a book on C for braceless "if"s. We could go toe to toe on high-quality C programs and whether they ever use them; nginx, for example, avoids them; dovecot doesn't. Both are exceptionally high quality C codebases.
Not that you have anything to prove to me, but I reject all your examples, and think you were too cavalier about judging K&R.
But I appreciate the response (and thus the opportunity to piously respond to it). :)