TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Deconstructing K&R C (2010)

149 pointsby experiment0over 12 years ago

18 comments

brudgersover 12 years ago
Shaw mischaracterizes K&#38;R by making anachronistic assumptions about its intended audience and ignoring the context in which it was written.<p>When it was written, a beginning C programmer was most likely coming from a background in assembly and accessing the computer as a professional in the workplace or a student with substantial privileges. The intended audience was sitting near the cutting edge and was assumed to be sophisticated. Data validation could be left as an exercise for the reader in good conscience.<p>This audience is distinctly different from those who learned programming typing code from magazines and Shaw's current audience for whom he is simulating that experience.<p>Editorially, K&#38;R has chosen to remain a slender tome. It has let others create fat cookbooks and "for idiots". Forty years on, Shaw criticizes the <i>Wright Flyer</i> by the criteria of Second World War aviation.<p>We don't hold K&#38;R on a pedestal because of its pedagogical methods, but because of the power of the language it describes. <i>The C Programming Language</i> was a byproduct of creating a language.<p>Kernigan and Ritchie were programming. Their book is properly judged by different standards than Shaw's educational project.<p>None of which is to suggest that Shaw"s project may not achieve a comparable level of esteem
评论 #5012968 未加载
评论 #5013346 未加载
评论 #5013074 未加载
评论 #5014052 未加载
zeteoover 12 years ago
&#62; we will be modernizing the code in K&#38;RC [...] It will be more verbose, but it will be clearer<p>It's been at least a year since the article first showed up on HN, and the author still hasn't made good on this promise. It's actually hard to do, because verbosity and clarity are usually at odds with each other.<p>One of the main attractions of K&#38;R C is exactly its <i>lack</i> of verbosity, its extraordinarily high content-to-length ratio. In a very short space you learn to do a lot of sophisticated programming, and most if not all code examples fit on one page or less.<p>Of course, optimizing for conciseness has its costs, as anyone who has debugged segmentation faults knows. So you avoid some of this shooting-yourself-in-the-foot that C is infamous for by using various crutches: add an extra argument for some functions, build your own Pascal-style strings etc. And if you pass in external input then you should definitely use some of them, such as strlcpy (which is actually preferable to the four-argument function that this article is getting to).<p>But there are also lots of cases where plain old strcpy will do fine, and for simplicity sake it's better to use it. I believe one of these cases is a learning experience in which you want to get the big story as soon as possible, and are willing to wait until later to get acquainted with the inevitable caveats and detours.
评论 #5013257 未加载
NickPollardover 12 years ago
I think Zed is right to point these errors out - there are quite a lot of issues with edge case inputs and undeclared assumptions, that people definitely need to hear about.<p>That said, he appears to be dealing in absolutes too much. If you care about performance (and let's face it, if you're using C you do, otherwise you probably shouldn't be using C) then sometimes you can't handle as much error checking or error correcting as you'd like.<p>In games (where most of my experience is), it's common to have functions that are 'unsafe' by his definition, but that are hidden in compilation units and not exposed in the header, so that the programmer can control exactly where they're called from. If you have a limited number of 'gatekeeper' interface functions that are actually called from outside the module, and these either check/sanitise/assert on their inputs, then the internal private functions can safely assume that they have valid input and just run as quickly and as simply as possibly.
评论 #5012597 未加载
评论 #5012604 未加载
评论 #5013647 未加载
elibenover 12 years ago
<p><pre><code> // use heap memory as many modern systems do char *line = malloc(MAXLINE); char *longest = malloc(MAXLINE); assert(line != NULL &#38;&#38; longest != NULL &#38;&#38; "memory error"); // initialize it but make a classic "off by one" error for(i = 0; i &#60; MAXLINE; i++) { line[i] = 'a'; } </code></pre> So, you create something that does not fulfill the C library invariant of what constitutes a "string", and then pass it to a copy function that assumes this invariant? It isn't a fair thing to do, and frankly, I doubt it many beginner programmers care about things like this. Yes, they may run into such a "defect" and be very miserable for a while, but that will just teach them about debugging, and most important, invariants.<p>Zed, I appreciate your work, but if this is the direction you'll be taking with these articles, then don't bother.
评论 #5012600 未加载
评论 #5012572 未加载
评论 #5012806 未加载
评论 #5012645 未加载
Camilloover 12 years ago
There is no reason to assume that the correct length parameters would be passed to safercopy. Indeed, there are many buffer overflows and off-by-one errors in C programs which involve buffers with explicit size values instead of null-terminated C strings.<p>The real problem with C is that it relies on bare pointers, where it would have been better to use slice-type structures that describe a buffer by pairing the base pointer and size, so that they are naturally kept in sync. This article takes a lot of time to "deconstruct" C strings, but never gets to the real issue.<p>The "stylistic issue" is also debatable. With the indentation given in the example, nobody would think that the "while-loop will loop both if-statements", as the author claims.
评论 #5013070 未加载
judofyrover 12 years ago
<p><pre><code> A = {'a','b','\0'}; B = {'a', 'b', '\0'}; safercopy(2, A, 2, B); A = {'a','b'}; B = {'a', 'b', '\0'}; safercopy(2, A, 2, B); A = {'a','b','\0'}; B = {'a', 'b'}; safercopy(2, A, 2, B); A = {'a','b'}; B = {'a', 'b'}; safercopy(2, A, 2, B); </code></pre> This analysis only tries different values of A and B, not the lengths. A proper analysis of "for what values does it fail" should include <i>all</i> parameters. What happens if you do `safercopy(3, A, 2, B)` or `safercopy(3, A, 3, B)`?
评论 #5012995 未加载
评论 #5013888 未加载
michaelfeathersover 12 years ago
Zed is dinging examples in K&#38;R for incorrectness, but he's inadvertently deconstructing the notion of correctness. It's more contextual than most developers want to believe.
评论 #5012564 未加载
foxhillover 12 years ago
the point of the exercise is to understand how a copy works, and stylistic issues aside, the point is made.<p>if you supply a function with inputs outside of it's specification (NULL-terminated strings), then undefined behaviour is (by definition) going to happen.<p>besides, what's to stop someone from calling safercopy like so;<p><pre><code> safercopy(strlen(str1), str1, strlen(str1), str2); </code></pre> then strlen will fail (albeit a bit more safely - perhaps).<p>it's a safe bet, that in production code, we'll not be working with fixed length strings. so we need to get the length of the string somehow. all his safercopy does identify a problem that he himself already points out is impossible to solve - how do we differentiate from a NULL-terminated string, and one that isn't?<p>the only real solution (i can think of) is a string class, where the constructor is guaranteed to return valid (or no) strings. then (assuming other functions can't overwrite our memory - already an unsafe assumption) we could guarantee a safe string copy.<p>programming is hard.
coofluenceover 12 years ago
I am wondering when will the author take on correcting errors in MMIX code in Knuth's books. He will at least earn a hex dollar for his efforts.<p>Jokes apart, I admire the bravery in questioning K&#38;R C's status. I have only a few personal insights to share as I don't code much these days.<p>1. I got introduced to C in 80's via some popular book. K&#38;R not only taught me C but also was my entry point into the systems programing world. Before K&#38;R, the BASIC programming books never allowed me to deal with memory or interrupt vectors in the way C allowed me.<p>2. C has a great power dynamic built in to it. You are on your own in dealing with this power. It's you who crashed the machine, not C and surely not K&#38;R C.<p>3. Almost every language since C has borrowed something from C. Hence, anytime I saw a familiar notation or code block in any language that reminded me of C, I got confidence that I can learn this language.<p>K&#38;R's many virtues give it an unique status. It did something that no C book or website can do it. It is the word of the language designer themselves. They shared their reasons of the choices they made.
experiment0over 12 years ago
Theres an analysis of his deconstruction here:<p><a href="http://functional-orbitz.blogspot.se/2013/01/deconstructing-zeds-k-deconstruction.html" rel="nofollow">http://functional-orbitz.blogspot.se/2013/01/deconstructing-...</a>
Prolepsover 12 years ago
Even if I made a function copy(char to[], char from[], int lenTo, int lenFrom) it would still be incorrect using his reasoning because most of the possible inputs would still cause the software to crash. I could symply add a wrong lenTo and lenFrom.
评论 #5012905 未加载
xentroniumover 12 years ago
I don't understand it. His solution to non-safe introduction to non-safe language is to slap defensive checks everywhere? I am not sure that scaring his students shitless by having them check every input is as effective as concise explanation why and when you should check your inputs.<p>Criticizing K&#38;R because of their safety assumptions is a faux pas.
aufreak3over 12 years ago
Though Shaw raises a valid point based on the fact that we program in more diverse and hostile situations today than K&#38;R did back in their days, I'm unsure how deep one needs to go into program correctness when teaching a language. Wouldn't it suffice, for example, to have program correctness highlighted as a chapter?<p>Take this -<p>&#62; Also assume that the safercopy() function uses a for-loop that does not test for a '\0' only, but instead uses the given lengths to determine the amount to copy.<p>It is possible to write a safercopy() conforming to that loose specification that will not terminate. Just make the test something like "i != length" instead of "i &#60; length". Then you can supply negative length arguments and get it to fail. Of course, that would be stupid, but it already illustrates the art of specification. .... Well, with finite precision integers, "i != length" would terminate at <i>some</i> point due to wrap around, but would take the universe to end if you'd used 128bit integers. To do it even more simply, `safercopy(1,2,3,4)` can crash the program.<p>Is the moral of this story that programs are not valid outside the context they were created for? .. or is it to never use data structures whose integrity cannot be proved without failure? .. or is it that proving a program's correctness using some method only indicates a failure of imagination? .. or, to put it differently, that you can only prove a program wrong but never one right?
mikeashover 12 years ago
This article is bashing just for the sake of bashing. While it pretends to offer constructive critiques and solutions, it fails miserably. One can certainly have productive discussions about the proper way to handle buffers in C, but this isn't it. Zed Shaw should stick to Ruby or whatever area he's actually good at.
评论 #5013064 未加载
killahpriestover 12 years ago
Annoyingly clever. Even while running Ito JavaScript I have to debate whether I should be annoyingly clever or not.<p><pre><code> /* bad use of while loop with compound if-statement */ while ((len = getline(line, MAXLINE)) &#62; 0) if (len &#62; max) { max = len; copy(longest, line); } if (max &#62; 0) /* there was a line */ printf("%s", longest); </code></pre> What do you do?
评论 #5013183 未加载
评论 #5012630 未加载
评论 #5012623 未加载
mkummover 12 years ago
I have been through both, K&#38;R and Shaw. K&#38;R is the resource I point new developers to who want to learn C.
mtkdover 12 years ago
This book introduced me to modern languages, from my previous experience coding in assembler. It inspired the millions of lines of code I've written since.<p>I now understand why my subsequent programs, and those of many in my generation, have been riddled with bugs for 3 decades.
评论 #5012606 未加载
评论 #5013088 未加载
dakimovover 12 years ago
Ironically, I most likely wouldn't hire Kernighan or Ritchie because of their poor programming style.
评论 #5013591 未加载
评论 #5012976 未加载
评论 #5012846 未加载
评论 #5014777 未加载
评论 #5013105 未加载