Live data from Hacker News

To become a good C programmer (2011)

fabiensanglard.net

61–70 of 135 posts

Re: To become a good C programmer (2011)

#61
post #58

Earlier quoted context omitted.

Rust isn't viable for embedded platforms, at least not yet. It's not as easy to compile it to the most obscure ISAs as C, and the little support it has for stuff like STM32 is restricted to just that group of microcontrollers and doesn't support the entire ARM range. Maybe in the future? I'm looking forward to that day! Go is probably never going to run on microcontrollers due to its very big overhead. C perfectly ma…

> Every single design decision about C was made with the computer in mind. The only problem is that computers have changed a bit in the last 50 years, and C largely hasn't. There are a couple issues: First, C was designed for single-pass compilers, because the PDP-7 it was designed for was too small to actually run much fancier of a compiler. So C is seriously sub-optimal for optimization in a lot of ways (because th…

> CPU performance has completely outstripped memory perf, so memory hierarchies and locality are everything > they don't show up in the language at all... requires knowing things that the code wouldn't suggest at all

I'm utterly confused at this.

It's trivial to layout memory as you please, where you please, very directly, in C. Set a pointer to and address and write to it. Better yet, I can define a packed struct that maps to a peripheral, point it to its memory address from a data sheet, and have a nice human readable way of controlling it: MyPIECDevice.sample_rate = 2000.

Keeping things physically close in memory has always been a strong requirement, as long as cache, pages, and larger than one-byte-memory buses have existed.

Re: To become a good C programmer (2011)

#62
post #61
post #58

Earlier quoted context omitted.

> Every single design decision about C was made with the computer in mind. The only problem is that computers have changed a bit in the last 50 years, and C largely hasn't. There are a couple issues: First, C was designed for single-pass compilers, because the PDP-7 it was designed for was too small to actually run much fancier of a compiler. So C is seriously sub-optimal for optimization in a lot of ways (because th…

> CPU performance has completely outstripped memory perf, so memory hierarchies and locality are everything > they don't show up in the language at all... requires knowing things that the code wouldn't suggest at all I'm utterly confused at this. It's trivial to layout memory as you please, where you please, very directly, in C. Set a pointer to and address and write to it. Better yet, I can define a packed struct th…

Give me an example of where C is allowed to optimize your data layout and/or locality. Afaik it is incredibly restrictive in this sense, because of how well defined it is. The less things it gives as guarantees with regards to layout the more wiggle room it would have, and languages like C cannot do some things that languages with a gc can do that can improve cache locality.

Re: To become a good C programmer (2011)

#63

One of the things I tend to think about these days is return on investment. I spent several years at the beginning of my career being a bad and then mediocre C programmer, and once I found a few other languages, I got the sense that being a mediocre-to-good programmer in these languages would be much easier, and that seems to have been borne out. Late into a career investing in other areas, what's the advantage of be…

Rust isn't viable for embedded platforms, at least not yet. It's not as easy to compile it to the most obscure ISAs as C, and the little support it has for stuff like STM32 is restricted to just that group of microcontrollers and doesn't support the entire ARM range. Maybe in the future? I'm looking forward to that day! Go is probably never going to run on microcontrollers due to its very big overhead. C perfectly ma…

> Rust isn't viable for embedded platforms, at least not yet.

no_std allows the important hooks of panicking, output and allocation to be implemented by the user. It's also very easy to put in hard-coded pointers that represent memory-mapped hardware. And there's no GC. Furthermore, it's entirely possible to convert only a portion of a project to using Rust while working to gradually to replace/reimplement.

> If I were to make one change to C, it would be to completely rip out the #include system [preprocessor] and bring a proper modules system.

Congratulations, you've just reinvented Java, D, Rust and Go.

> Apart from that, it's pretty much perfect.

This seems like a religious opinion rather than having understanding of different paradigms. Have you been paying attention to why Java, Erlang, Go, Rust and exist? Rust has numerous advantages over C that eliminate entire categories of problems without sacrificing speed. If you can't see that, then maybe you don't want to see it.

Re: To become a good C programmer (2011)

#64
post #61

Earlier quoted context omitted.

> CPU performance has completely outstripped memory perf, so memory hierarchies and locality are everything > they don't show up in the language at all... requires knowing things that the code wouldn't suggest at all I'm utterly confused at this. It's trivial to layout memory as you please, where you please, very directly, in C. Set a pointer to and address and write to it. Better yet, I can define a packed struct th…

Give me an example of where C is allowed to optimize your data layout and/or locality. Afaik it is incredibly restrictive in this sense, because of how well defined it is. The less things it gives as guarantees with regards to layout the more wiggle room it would have, and languages like C cannot do some things that languages with a gc can do that can improve cache locality.

It's not, that's the point, the language/compiler cannot interfere with the programmer fine tuning data structures to suit the underlying architecture.

Re: To become a good C programmer (2011)

#65

In the 90s, most seriouc C programmers knew about these books. They were the core books most devs relied on and referred to. They're all good. I disagree with this comment: "No website is as good as a good book. And no good book is as good as a disassembly output." There are many websites today that are excellent. And there are many websites that cover obscure topics not found in books. Finally, I think it's importan…

Nuance is needed. Multiple sources form the overall picture. I found that doing hard things in an embedded or conventional shipped product team is the best way to learn, and that working with effective people who used a particular language reasonably defensively and obviously for maintainability contributed the most code value.

For example, I taught myself Pascal, C, C++, assembly and Java (badly) before attending undergrad. The good thing about the ugrad program I had was that there were SGI, HP-UX, Solaris and Linux boxes such that writing portable C was essential.. you couldn't turn in a project if make didn't work on every platform because they wouldn't say which one they would use ahead-of-time. Then, I had an embedded internship at GPS manufacturer to work on 900 Mhz and 2.4 GHz radio firmware where a C++ subset was used on a codebase that spanned about 100 products. Also, lots of refactoring test/flashing tools was required because of commented-out code remnants were checked-in and 2000-line megafunctions because interns just banged-out code without any enforced coding standards.

Re: To become a good C programmer (2011)

#66
post #24

It's unfortunate he doesn't list the POSIX system interface, which has personally become an absolute boon: https://pubs.opengroup.org/onlinepubs/9699919799/ You can search it using duckduckgo with !posix, too. Something else I've found infinitely useful when digging into musl libc or doing assembly programming, is the SYSV x64 ABI: https://refspecs.linuxfoundation.org/elf/x86_64-SysV-psABI.p...

Thanks for the link to the POSIX docs, looks very useful. More recent specs for the x64 ABI can be found at https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI

Re: To become a good C programmer (2011)

#67

I feel like I wrote that a decade ago. Wait. Damn. It WAS a decade ago. Amazingly the list is still relevant. I will try to check out the new suggestions on this thread.

I've found "Understanding and Using C Pointers" by Richard Reese, a really wonderful book.

Re: To become a good C programmer (2011)

#68
post #61
post #58

Earlier quoted context omitted.

> Every single design decision about C was made with the computer in mind. The only problem is that computers have changed a bit in the last 50 years, and C largely hasn't. There are a couple issues: First, C was designed for single-pass compilers, because the PDP-7 it was designed for was too small to actually run much fancier of a compiler. So C is seriously sub-optimal for optimization in a lot of ways (because th…

> CPU performance has completely outstripped memory perf, so memory hierarchies and locality are everything > they don't show up in the language at all... requires knowing things that the code wouldn't suggest at all I'm utterly confused at this. It's trivial to layout memory as you please, where you please, very directly, in C. Set a pointer to and address and write to it. Better yet, I can define a packed struct th…

> Set a pointer to and address and write to it. Better yet, I can define a packed struct that maps to a peripheral, point it to its memory address from a data sheet, and have a nice human readable way of controlling it: MyPIECDevice.sample_rate = 2000.

Just make sure you don't forget `volatile` in the right places. A lot of codebases end up just using their own wrappers written in asm for this kind of thing, because the developers have learned (rightly or wrongly) not to trust the compiler.

To be clear, it's not that hard to get the memory layout semantics you want in C. But issues around concurrent access, when it is acceptable for the compiler to omit loads & stores, whether an assignment is guaranteed to be a single load/store or possibly be split up (affects both semantics in the case of mmio and also atomicity), are all subtle questions, the answers to which are not at all suggested by the form of the code; The language is very much designed with the assumptions that (1) memory is just storage, so it's not important to be super precise on how reads and writes actually get done (in fairness, the lack of optimization in the original compilers probably made this more straightforward), and (2) concurrent access isn't really that important (the standard was completely silent on the issue of concurrency until C11). If you care about these issues there's a lot of rules lawyering you have to do to be sure your code isn't going to break if the compiler is cleverer than you are. A modern take on C should be much more explicit about semantically meaningful memory access.

I think you can make a sensible argument that wrt hierarchies C is at least not a heck of a lot worse than the instruction set, so maybe I'm conceding that point -- though the instruction set hides a lot that's going on implicitly too. Some of this though I think is the ISA "coddling" C and C programs; in a legacy-free world it might make more sense to have an ISA let the programmer deal with issues around cache coherence. I could imagine some smartly designed system software using the cache in ways that can't be done right now (example: a copying garbage collector with thread-local nurseries that are (1) small enough to fit in cache (2) never evicted and (3) never synced to main memory, because they're thread-local anyway). Experimental ISA design is well outside my area of competency though, so it's possible I'm talking out of my ass. But the general sentiment that modern ISAs hide a lot from the systems programmer and that other directions might make sense is something that I've heard more knowledgeable people suggest as well.

Re: To become a good C programmer (2011)

#69
post #49

One of the things I tend to think about these days is return on investment. I spent several years at the beginning of my career being a bad and then mediocre C programmer, and once I found a few other languages, I got the sense that being a mediocre-to-good programmer in these languages would be much easier, and that seems to have been borne out. Late into a career investing in other areas, what's the advantage of be…

C is still king in embedded systems. It is also great at making you aware of the machine. In C, very little is happening behind the scene. If you want something to happen, you need write some code. Objects will not initialize themselves, allocated memory will not free itself, no smart reference mechanisms, just explicit pointers. This understanding of the machine will help understanding why higher level langages beha…

[deleted]

Re: To become a good C programmer (2011)

#70
post #49

One of the things I tend to think about these days is return on investment. I spent several years at the beginning of my career being a bad and then mediocre C programmer, and once I found a few other languages, I got the sense that being a mediocre-to-good programmer in these languages would be much easier, and that seems to have been borne out. Late into a career investing in other areas, what's the advantage of be…

C is still king in embedded systems. It is also great at making you aware of the machine. In C, very little is happening behind the scene. If you want something to happen, you need write some code. Objects will not initialize themselves, allocated memory will not free itself, no smart reference mechanisms, just explicit pointers. This understanding of the machine will help understanding why higher level langages beha…

[deleted]
Post reply on HN