Hacker News new | comments | show | ask | jobs | submit login

Knowing C has made me a better and much more versatile programmer than I would be without it. For instance, a while back I had to diagnose a JVM core dumping sporadically, and I was able to use my knowledge of C to try to recover valid return addresses from a corrupted stack, figure out there was a signal handler block on the stack, then further unwind from there to find out the whole story of what likely caused the crash.

Knowing C also helps me write more performant code. Fast Java code ends up looking like C code written in Java. For instance, netty 4 implemented their own custom memory allocator to avoid heap pressure. Cassandra also has their own manual memory pools to try to improve performance, and VoltDB ended up implementing much of their database in C++. I've been able to speed up significant chunks of Java code by putting my "C" hat on.

I would recommend every college student learn C, and learn it from the perspective of an "abstract machine" language, how your C code will interact with the OS and underlying hardware, and what assembly a compiler may generate. I would consider learning C for pedagogical purposes to be much more important than C++.




> I would recommend every college student learn C, and learn it from the perspective of an "abstract machine" language, how your C code will interact with the OS and underlying hardware, and what assembly a compiler may generate.

Do note that these are two very different things. The C abstract machine as defined by the standard is sometimes so different from the actual machines you're going to run your code on, that you get these fine undefined behaviour things that everybody's on about.

Please learn both, indeed, and stress the differences; then highlight the advantages of C. C is a dangerous, but powerful tool, and the necessity of warning students about things should not inhibit learning C.


> C is a dangerous, but powerful tool, and the necessity of warning students about things should not inhibit learning C.

C is sharp, yes. It's also a universal interface. Almost every language has bindings for C, and C has bindings for almost everything.


> Almost every language has bindings for C, and C has bindings for almost everything.

In my mind this is the #1 reason to learn C. And it's unlikely that C++ will replace C in this role anytime soon as C++ has many more ways for an ABI to go wrong.


It often works to implement well to implement your code in C++ and have a C interface (using extern "C") wrapped around it to be consumed be interfaced with by other languages.


I feel the same. Even when debugging JavaScript or C# performance problems I often have insights from a C perspective that people who have only learned Java or JavaScript don't have. I haven't learned much assembly but I think some level of it would also be a very good thing.

Once whole operating systems are written in Rust maybe Rust will be the most important language but until then it's C. C++ doesn't really count. I don't think you can do any serious C++ without knowing C really well.


I was with you until the part about C++. I spent very little part of my career writing C(mostly embedded hobbies) but still managed to pick up all the important bits(memory layout, CPU caches, allocation costs, processor pipelines and the like) from C++.

Really it wasn't too long ago that the STL just wasn't good enough for high performance code and we rolled our own containers/pooling/everything. Modern C++ is a very much a different beast these days.


I think I expressed my thoughts wrong. I didn't mean to say that you need to learn C to use C++ but that if you do any serious C++ work you will know a lot about the way C works. I don't think you will go very far in C++ if you don't understand pointers, heap vs. stack, when to allocate and release memory and a lot of other stuff.


Another important thing is understanding what's going on under the hood with C++ features— like, how you'd compile C++ into C. I don't put a ton of weight in it, but I enjoy engaging interview candidates about what's going on with virtual methods, casting classes, specialization with polymorphism vs templates, "public virtual" and multiple inheritance, etc etc. Like I say, no one thing is super interesting on its own, and its not a textbook answer I'm looking for, more just a sign that someone was curious enough to dig in at some point and figure out how the sausage was made.


Ah, I think we're just arguing semantics then. I see that as very much a part of C++(new vs malloc only has some small subtle differences for instance).

I will say if you don't understand pointers you're in for a world of pain in C++.


> I don't think you will go very far in C++ if you don't understand pointers, heap vs. stack, when to allocate and release memory and a lot of other stuff.

This reads to me as if you ascribe those attributes to C, which simply isn't true; C++ has an equal (to C) concept of pointer, allocation/freeing (and, with RAII, I would argue superior).


> "For instance, a while back I had to diagnose a JVM core dumping sporadically, and I was able to use my knowledge of C to try to recover valid return addresses from a corrupted stack, figure out there was a signal handler block on the stack, then further unwind from there to find out the whole story of what likely caused the crash."

Okay, but is that knowledge coming from coding in C, or it coming from debugging low-level code? I don't know what tool(s) you used to do that debugging, but if I assume for a second that you were using GDB, wasn't the main benefit of your past C experience (in this case) the exposure to tools like GDB, rather than your C knowledge being key in enabling you to dissect that JVM issue?


I think it's the C knowledge. I assume JVM is written in C or C++ so with C knowledge you can understand better how it works.


Can it be replaced with Rust nowadays? Is it low-level enough? Or borrow checker and lifetimes defeat the whole purpose?


For teaching purposes in a university I don't know if rust would be better or not. Keep in mind that the goal isn't necessarily to learn C the language; it's to learn enough of the core language to explore things like:

* How the code is executed on modern hardware and operating systems.

* How various language features might be compiled to assembly

* Memory layouts for things like stack frames, how a simple heap allocator might work, array layouts, layouts for other structures like linked lists, etc.

* The relative cost of various operations and how to write code that is cache friendly.

* How debuggers generally work and how to debug code.

Could these things be taught equally well or better in an undergraduate seeing using rust? Honestly I don't know; I know very little about Rust. I can say that I think C++ is a worse language for this purpose because of the language's complexity and because of features that aren't well suited for the above purposes.

I have heard, for instance, that's it's actually very difficult in rust to write a linked list without dropping to unsafe code. I would consider this a bad thing for the above purposes.


> * How the code is executed on modern hardware and operating systems.

Does anyone know this at this point? With pipelining, out of order execution, vectorisation, register renaming, speculative execution, buffered micro-op fusing and what have you, it's very hard to say general things about how the code executes on the actual hardware.


Perhaps, "Understand the model of how code pretends to be executed"? Pipelining, etc. are meant to produce the same results as the older/simpler systems. You need to understand that that's not quite reality anymore, but as a basic model it's fine.


Sure, but at that point you are content with learning "the x86 virtual machine" -- and is that fundamentally different from being content with learning "the Java virtual machine"?

I'm arguing that it's a matter of degree, not of kind. People make it seem like it's the latter.


It's different in kind. The JVM completely abstracts away things like class loading from the perspective of bytecode - that stuff seems to happen like magic. Ditto exception handling, stack frame linkage, memory allocation, etc.

Viewing all of code and data living together in a big array is important, I think. You don't understand e.g. dynamically generated thunks and shims without seeing the duality of code and data at the execution level.


Short answer: because cache misses are 10x more common and dominate the time saved from pretty much all of those features.

Get your cache misses in order(which is easy to understand in the C model) and you're ahead of 95% of the curve(plus you get a 10-50x performance bump as a reward).


Of course not. With the meltdown/spectre vulnerabilities and mitigations we see that how a processor/OS/program stack executes code can change from year to year or month to month, with significant performance differences. Maybe that's an exceptional blip, maybe it's a portent for the future.


> I have heard, for instance, that's it's actually very difficult in rust to write a linked list without dropping to unsafe code.

It is also hard in C to write a linked list without dropping to unsafe code. In fact, it is hard in C to add frigging signed integers without dropping to unsafe code.


My guess is that for this author's purposes, Rust is in the same place as C++. It can do the low level things, but you tend to spend more of your time working with higher level libraries that hide the nuts-and-blots details like allocation.


Rust libraries don't really hide allocation any more than modern C libraries do. (And if you aren't using modern libraries for stuff like string handling in C, you should be.)


Isn't the point of this whole argument about avoiding abstraction?


I don't see any way in which string.h is less abstract in the "close to metal" sense than a real string or vector library (or Rust) is. The standard C library offers abstractions, just poor ones.


Not sure why this is being downvoted. Whether or not anyone out there likes Rust, dislikes Rust, or is completely apathetic to Rust, we can unanimously agree that the standard string-handling routines in C are quite poor. This isn't a controversial statement.


What modern C libraries do you have in mind?




Applications are open for YC Winter 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: