Live data from Hacker News

C Craft

crypto.stanford.edu

21–30 of 60 posts

Re: C Craft

#22

well, he mentions hating OO languages because it makes it hard for him to program in a style similar to C. That's a bit like saying you hate hate hammers because they don't work with screws very well.

No, his probelm with OO is that inheritance is problematic as a primary means of abstraction . It sounds nice on paper, but can lead to horribly unmaintainable code and wasting time arguing over specifics of tangled inheritance hierarchies. (This is a bigger issue in statically typed OO languages - being able to just send a message and get an exception if the recipient doesn't support that interface helps quite a bit…

The point still remains that he arrived to this conclusion by misusing his tools. The problems of inheritance are not a universally recognized truth. There are plenty of OO advocates who believe that inheritance is perfectly fine. Maybe the issue with inheritance in OO languages is people misusing their language.

Re: C Craft

#23
post #10

I think it's telling that the very first example to use dynamic allocation has a memory corruption bug. struct { int n; char c[0]; } *foo = malloc(16); /* sizeof(*foo) probably 4, so 12 bytes follow */ foo->n = 16; for(int i = 0; i n. oops. */ foo->c[i] = 'a' + i; } Not that I don't love C for terseness and power or appreciate the systems one can build in it, but seriously.

Give a man enough rope to hang himself, and he'll shoot himself in the foot.

Re: C Craft

#24
Sounds to me like he was trying to do low-level programming using an OO language, and he finally "comes home" to a good low level language.

Re: C Craft

#25
The criticism of Java language is very much to the point (re: verbosity, inheritance). There's some confusion where he calls anonymous classes implementing interfaces "abstract classes with virtual methods"; that's not to say that it's not an awkward approach to closures and function pointers. There's also criticism of synchronized and the Thread class, but there's no mention of the strong points (Doug Lea's java.util.concurrent).

However, the criticism of JVM seems like it's written in 1999 about the Blackdown JVM (Josh Bloch in his interview in Coders At Work attributes much distrust of Java earlier on at Google to experience with this platform). Hot-spot can, many times, be within 10-15% of C's performance. In many cases code running on the JVM will outperform C++'s runtime (and particularly boost).

That's not to say there aren't issues: garbage collection pauses, the stack based nature -- rightly -- is pointed out as an impediment, but it's odd that LLVM isn't mention. However, excluding JVM due to performance (especially when used with modern languages, e.g. Scala, Clojure, Ruby, Javascript) seems short-sighted. See Cliff Click's post on JVM performance:

http://blogs.azulsystems.com/cliff/2009/09/java-vs-c-perform...

Repeat after me: HotSpot is not Blackdown, 1.5+ is not 1.2 (you have non-blocking I/O -- even though NIO is still painful to use, you have autoboxing, you have foreach, you have -- for all their limitations -- generics, you have annotations), you can run more than Java on the JVM. Even if you do choose Java (which has many flaws, not the least of them being a marketing-driven language, aimed at enterprise C++ developers, rather than a language made by hackers for themselves), you don't have to use Spring and J2EE. In most cases performance is a MacGuffin when it comes to Java and JVM.

Re: C Craft

#26
post #10

I think it's telling that the very first example to use dynamic allocation has a memory corruption bug. struct { int n; char c[0]; } *foo = malloc(16); /* sizeof(*foo) probably 4, so 12 bytes follow */ foo->n = 16; for(int i = 0; i n. oops. */ foo->c[i] = 'a' + i; } Not that I don't love C for terseness and power or appreciate the systems one can build in it, but seriously.

His warning against using #ifdef is also misplaced. I have written assembler (GAS) using the GAS x86 asm preprocessor to write portable x86/x86-64 assembly code in one file. Far simpler and shorter than writing the same code in two files. Basically, whenever he says "never" do something he means he doesn't like to do it. For example, his answer to not having a multi-level function break is a nested helper function. G…

I'm curious: are the standard IO functions that much more efficient than a mmap'd file? What makes you choose one over the other?

I usually just use standard IO, unless I have a large file that might be randomly accessed by multiple processes. In that case I'll use a mmap. But, I don't code in C very much anymore, so I was wondering how much of a difference there really is.

Re: C Craft

#27

Earlier quoted context omitted.

No, his probelm with OO is that inheritance is problematic as a primary means of abstraction . It sounds nice on paper, but can lead to horribly unmaintainable code and wasting time arguing over specifics of tangled inheritance hierarchies. (This is a bigger issue in statically typed OO languages - being able to just send a message and get an exception if the recipient doesn't support that interface helps quite a bit…

The point still remains that he arrived to this conclusion by misusing his tools. The problems of inheritance are not a universally recognized truth. There are plenty of OO advocates who believe that inheritance is perfectly fine. Maybe the issue with inheritance in OO languages is people misusing their language.

Working on any reasonably large project in a (mainstream) OO language makes dealing with someone's code that misuses inheritance incredibly likely, and design errors in class hierarchies can inflict their problems on everything they touch. OO has been sold as a tool to reduce complexity, but can become a major source of it as projects develop.

Also, reading code with several levels of inheritance (more than three, perhaps) means dealing with several levels of spaghetti code - the code becomes a mess of "this does that, but no, wait, it doesn't anymore here, though here it does that except it does this first."

Re: C Craft

#28
post #12
post #11

The first section I looked at contains a buffer overflow: http://crypto.stanford.edu/~blynn/c/ch03.html#_when_are_size... Great C craft :-)

Why is this downvoted? It is a serious bug in the example code.

It might be because it says the same thing as another comment, which was probably posted earlier. As such, it's noise in the conversation.

Re: C Craft

#29
post #13

C provides my daily bread and I absolutely love the language. That said, sometimes(I mean often) it does hurt when I have to work at a higher abstraction level in some fancier language and I keep thinking on what is going behind the scenes.

Running a profiler can reassure you that while yes, your HLL code may be doing decadently inefficient things for sake of developer convenience, most of the time it has a negligible effect on overall performance. Just rewrite those parts in C if you have to and you can get the best of both worlds.

Re: C Craft

#30
post #10

I think it's telling that the very first example to use dynamic allocation has a memory corruption bug. struct { int n; char c[0]; } *foo = malloc(16); /* sizeof(*foo) probably 4, so 12 bytes follow */ foo->n = 16; for(int i = 0; i n. oops. */ foo->c[i] = 'a' + i; } Not that I don't love C for terseness and power or appreciate the systems one can build in it, but seriously.

I noticed that too, and what's weird is that's not at all how you should do it. Since the char c[0] has zero size you can do sizeof on the struct so that you can do the malloc correctly. struct thing { int n; char c[0]; }; int i_need = 16; struct thing * foo = malloc(sizeof(struct thing)+i_need); foo->n = i_need; for (int i = 0; i n; i++ ) { foo->c[i] = 'a' + i; } And if your compiler won't let you do char c[0] you c…

Well, being pedantic, that should be

  struct thing *foo = malloc(sizeof(struct thing) + sizeof(char) * i_need);
since sizeof(char) isn't guaranteed to be 1 byte on all systems.
Post reply on HN