Live data from Hacker News

Deconstructing "K&R C"

c.learncodethehardway.org

31–40 of 136 posts

Re: Deconstructing "K&R C"

#31
post #8

I'm confused. What is the "defect" in K&R's "copy(char to[], char from[])" function? The author notes that "the second this function is called...without a trailing '\0' character, then you'll hit difficult to debug errors", but no function with that signature could possibly work in this case. The built-in "strcpy" function has the exact same limitation. Does the author have a problem with it as well? Null-termination…

Huh? My C programming is in the distant past, so I might be forgetting. But strcpy does assume a terminal zero, doesn't it? E.g., http://linux.die.net/man/3/strcpy . It sounds like you are talking about strncpy or memcpy.

I'm confused by your comment. strcpy assumes that the string to be copied ends with a NUL. The case described in the link violated that assumption and caused a segfault.

Re: Deconstructing "K&R C"

#32

Earlier quoted context omitted.

The built-in "strcpy" function has the exact same limitation. Does the author have a problem with it as well? Yes. From the linked chapter: we avoided classic style C strings in this book From an earlier chapter on strings: The source of almost all bugs in C come from forgetting to have enough space, or forgetting to put a '\0' at the end of a string. In fact it's so common and hard to get right that the majority of…

"the majority of good C code just doesn't use C style strings..." Nice. In the 23 years I have worked on C language products, I've never worked on "good C code" by this definition. The cool thing about this guys book, I guess, is that by avoiding all the things about the language he doesn't like, any reader will be wholly unprepared for C in the Real World after this book.

The approach looks similar to the one in "JavaScript: the good parts" I am worried about the same while reading it: ok, here's the right way to do e.g. inheritance, but how do they do it in real world?

Re: Deconstructing "K&R C"

#33

> Braces Are Free, Use Them I disagree. Braces have a cognitive load, particularly if they're given whole lines to themselves. Which is easier to read, while ((len = getline(line, MAXLINE)) > 0) if (len > max) { max = len; copy(longest, line); } if (max > 0) /* there was a line */ printf("%s", longest); or while ((len = getline(line, MAXLINE)) > 0) { if (len > max) { max = len; copy(longest, line); } } if (max > 0) /…

Because it's the style I use, and because I don't need to bug-check the indented code to make sure it's braced correctly, I find this easiest to read:

  while ((len = getline(line, MAXLINE)) > 0) {
      if (len > max) {
          max = len;
          copy(longest, line);
      }
  }
  if (max > 0) { /* there was a line */
      printf("%s", longest);
  }

Re: Deconstructing "K&R C"

#34
post #11

Earlier quoted context omitted.

One problem with it is that on most compilers if you compile with optimizations it will remove the assertion. Now the code is no longer guarded against malloc failures and will just segfault. If the intent is to teach people how to handle malloc failures gracefully, it's not that great of an example.

Why do you think the compiler with optimizations will remove the assertion? The compiler will realise that: assert(assert(line != NULL && longest != NULL && "memory error"); Is equivalent to: assert(line != NULL && longest != NULL); But there doesn't seem anything wrong with that.

In support of tptacek's comment, an abbreviate version of what's in assert.h on my OSX system:

  #ifdef NDEBUG
  #define assert(e)   ((void)0)
  #else

  #define assert(e)  \
    ((void) ((e) ? 0 : __assert (#e, __FILE__, __LINE__)))
  #define __assert(e, file, line) \
    ((void)printf ("%s:%u: failed assertion `%s'\n", file, line, e), abort())
So, if NDEBUG ("no debug") is defined, which it is if optimizations are turned on, asserts become a no-op.

Re: Deconstructing "K&R C"

#35

Earlier quoted context omitted.

The built-in "strcpy" function has the exact same limitation. Does the author have a problem with it as well? Yes. From the linked chapter: we avoided classic style C strings in this book From an earlier chapter on strings: The source of almost all bugs in C come from forgetting to have enough space, or forgetting to put a '\0' at the end of a string. In fact it's so common and hard to get right that the majority of…

"the majority of good C code just doesn't use C style strings..." Nice. In the 23 years I have worked on C language products, I've never worked on "good C code" by this definition. The cool thing about this guys book, I guess, is that by avoiding all the things about the language he doesn't like, any reader will be wholly unprepared for C in the Real World after this book.

This chapter is explicitly teaching people what the author's idea of bad C code is: It has them read some, then tells them specifically what the gotchas are, then asks them to code up test cases for the flaws and run them through Valgrind.

Where's the "avoiding" here?

And which of the skills being exercised - imagining what kinds of bad things could happen, writing executable test cases, detecting segfaults - are not useful in the real world?

Re: Deconstructing "K&R C"

#36

> Braces Are Free, Use Them I disagree. Braces have a cognitive load, particularly if they're given whole lines to themselves. Which is easier to read, while ((len = getline(line, MAXLINE)) > 0) if (len > max) { max = len; copy(longest, line); } if (max > 0) /* there was a line */ printf("%s", longest); or while ((len = getline(line, MAXLINE)) > 0) { if (len > max) { max = len; copy(longest, line); } } if (max > 0) /…

Easiest to read? The middle. The way I would write it for my own use is closest to the top, but the easiest to read is the middle.

Always using braces, and giving them their own lines makes nesting as unambiguous as possible and the extra white space reduces density making foreign code easier to digest.

Re: Deconstructing "K&R C"

#37
post #8

I'm confused. What is the "defect" in K&R's "copy(char to[], char from[])" function? The author notes that "the second this function is called...without a trailing '\0' character, then you'll hit difficult to debug errors", but no function with that signature could possibly work in this case. The built-in "strcpy" function has the exact same limitation. Does the author have a problem with it as well? Null-termination…

[deleted]

Re: Deconstructing "K&R C"

#38
"Before the switch to heap memory, this program probably ran just fine because the stack allocated memory will probably have a '\0' character at the end on accident."

Stack memory is not preinitialized to '0' either so using stack memory would show this 'defect' as well (as others have pointed out this is a defect in the calling code, not in copy).

Re: Deconstructing "K&R C"

#39

> Braces Are Free, Use Them I disagree. Braces have a cognitive load, particularly if they're given whole lines to themselves. Which is easier to read, while ((len = getline(line, MAXLINE)) > 0) if (len > max) { max = len; copy(longest, line); } if (max > 0) /* there was a line */ printf("%s", longest); or while ((len = getline(line, MAXLINE)) > 0) { if (len > max) { max = len; copy(longest, line); } } if (max > 0) /…

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.

SeanLuke, that is exactly how I'd write it too! ✼Whitesmith fistbump✼ — Related: I love the Wikipedia talk section on it: http://en.wikipedia.org/wiki/Talk:Indent_style#Whitesmiths_s...

Re: Deconstructing "K&R C"

#40

Earlier quoted context omitted.

I don't see what the big deal is here. He throws inputs at a function not meant to handle them and gets a segfault. Isn't this more-or-less expected from all C functions? We are getting separated from that kind of behavior. Nowadays the language is generally expected to protect you from yourself.

No, C is specifically for situations where you don't want the language to "protect you from yourself". E.g. systems programming where little or no runtime performance will be sacrificed to enable imperfect code to be safe.

Understood, it just catches people off guard and they get mad at C
Post reply on HN