1. 7
  1.  

  2. 20

    I saw this article earlier and decided not to submit. I was a bit disappointed with the content and here is why (note I didn’t check the linked ‘free’ book).

    1. The title speaks of a resurgence of C programming but the content has little to do with the language and recurring interest in C;
    2. They constantly intermix C and C++;
    3. It focuses solely on Arduinos & Raspberry Pi plus bits of seemingly random trivia.

    I expected a piece going deep on people re-discovering the importance of working on a lower level. Instead I found couple of passages that the language is still used to program hardware and that it influenced a lot of languages with it’s syntax.

    1. 5

      Thanks, this saved me some time trying to get psst their paywall.

    2. 14

      Without a comprehensive ad-blocker this is 100 words and a signup form.

      1. 9

        I recently started going through postgres' source code ( a pretty nice C codebase), and I gotta say it’s not the funnest experience. My main gripe is that people insist on writing C-only applications instead of relegating C to the “tight loop” (much like assembler was/is). There are too many issues that make C a much less fun experience on larger projects:

        • The most effective way to write clean control-flow structures is through preprocessor macros. Postgres linked-lists are managed through macros. A lot of system-dependent code ends up being set up through macros.
        • There’s not a real nice build system story. People tend to reach for “make + preprocessor definitions”, which causes a bit of difficulty when it comes to figuring out what your “real” entry point is without also figuring out the build mechanisms.
        • the low-level nature of C and lack of much introspection makes “exploratory debugging” extremely difficult.Most scripting languages give me a shell quickly. Other static languages have strong debuggers. In C there’s so much busywork needed to start inspecting projects that I usually end up just printfing a lot.

        Coming from doing a lot of Python recently, I generally realized how much of a slog working in C is. I know it’s more straightforward for bit-twiddling or embedded systems, but I’m pretty convinced that any medium-sized project or above should be jumping at opportunities to run the higher-level code in something else. Not because C is bad, but because other languages have such better tools for larger-scale projects.

        My current feeling is : “If your program is more than one file, and you don’t have a big reason to use C, don’t”. Seriosusly, look at the C FFI for Python, Lua, Java, Haskell…. even C++ will give you some better tools. Why not give yourself the gift of a real foreach/proper iteration? Or of nicer dependency management. Or code that can get real static analysis?

        For embedded systems: Lua can get pretty small. Or maybe a small Forth machine, even.

        For large open source projects: I have gone from newcomer to certain python projects to contributor in less than 24 hours. Wouldn’t it be nice to have more contributors? The learning curve is important.

        1. 8

          the low-level nature of C and lack of much introspection makes “exploratory debugging” extremely difficult.Most scripting languages give me a shell quickly. Other static languages have strong debuggers. In C there’s so much busywork needed to start inspecting projects that I usually end up just printfing a lot.

          Odd. I guess this is just a reflection of different backgrounds, but I find exactly the opposite. With C, in my experience it’s typically very easy to fire something up under gdb and step through it at whatever level is necessary. With python, in contrast, I occasionally reach for pdb, but it always ends up feeling like a cheesy little toy in comparison to gdb, so my debugging is consistently much more printf-heavy in Python than it is in C.

          1. 4

            So pdb as-is isn’t really much better than gdb. But if you use ipdb instead, you get auto-complete goodness and things from IPython that help a lot.

            Because Python is in a VM with GC, you can also use something like the gc module to find all objects that refer to an object you’re using. Imagine trying to find all the C structs that have a pointer to an object you’re working on! Pretty magical.

            Now if you start using something like objgraph you can even print out a nice diagram of objects that refer to your object, and then objects that refer to those, etc. It’s very helpful when trying to figure out how some object is being used, or when it’s being initialized.


            Another advantage you get in Python is that most libraries are shipped as python scripts, so you can also quickly modify your dependencies to help debugging. This means that I’ve been able to quickly go from “my code has a bug” to “this dependency has as bug”, to “I have monkeypatched my dependency and sent a patch to the dependency’s Github”.

            Python is a bit special though, because of how dynamic it is. I don’t think it would be an easy feat to implement a lot of this for C, even with a lot of debugging instrumentation. But it’s helped me out a lot when working on large applications.

            1. 4

              you get auto-complete goodness and things from IPython that help a lot.

              But those aren’t the things that interest me in gdb – what I tend to do is things like “break when this value changes and the current expression id is 123”. Reverse stepping is another big one, although I actually find I don’t use it too much.

          2. 3

            The most effective way to write clean control-flow structures is through preprocessor macros. Postgres linked-lists are managed through macros.

            Stuff like this gives me an eye roll when people tell me how good C language is for stuff like Postgres. Yet, the big projects in C often avoid using the language itself in favor of custom languages they create with its fragile, macro system. They do this for portability, expressiveness, security, and so on. Might as well use a higher-level language w/ real macros that can generate C or just efficient ASM given base language wasn’t good enough in practice. Might not even need the macros for a lot of what they use it for now.

            1. 4

              Preprocessor macros are the worst. Especially when you are 4 macros deep, and find out one of the macros calls a put function to decrement a refcount.

              I’ve come to the conclusion that if clang-format can’t figure out your macro, its too complex. So far that logic has held steady.

            2. 3

              “The most effective way to write clean control-flow structures is through preprocessor macros.”

              What does this mean? I find that macro heavy code is almost always unnecessary and harder to read and maintain.

              1. 2

                The example I’ve seen a lot is for iteration. People will write a foreach macro to be able to write foreach(elt, list) instead of do{ elt = cur->elt; ... cur = cur->next;} while(cur) (plus omitted empty list check)

                C doesn’t give you a lot of tools apart from macros for control flow abstraction.

                1. 3

                  What you should do is write an iterator function, if you want it and not worry about trying to outguess the compiler. C programmers who use the pre-processor to make C pretend to be something else are following a long, but not so great, tradition that I think really started with the horrible bourne shell fake algol. http://oldhome.schmorp.de/marc/bournegol.html

            3. 8

              I’ve come around to C and I’ve been using it a lot lately and even still I don’t feel like C “went anywhere”.

              I spent a lot of time as a language zealot. And I still really like languages like Haskell and Lisp (and even Python) and would use them for a number of purposes. However, all of those other languages are “nice to have”. With C, there are large areas of computer science (practically speaking, at least) that are off limits if you’re not willing to learn it and learn it well.

              What I think happens over time is that good programmers gravitate toward established low-level languages over time. There may be 5 times as much difficulty in getting productive in C as compared to Ruby, but the time to learn a new language is minuscule over the course of a career. And there seems to be a pay-now-or-pay-forever dynamic to programming: you can learn the hard, math- and logic-intensive stuff that doesn’t change as frequently, or you can stick to the easier (but less proven) stuff that the cool kids are using, only to have to learn a new skill set in 6 months. At some point, people get sick of the “pay forever” model.

              1. 6

                I think there’s a deeper pattern here – I think good programmers will gravitate towards the lower level itself, and not low level languages in particular. When you move up the skill ladder from CRUD apps, understanding somewhat basic concepts like scheduling and memory management is vital. It doesn’t even matter if it’s C or Java, in the Java world there is a demand for people who understand JVM intricacies like its concurrency and garbage collection models and their implications on code performance.

              2. 2

                Interestingly, one can substitute Ada/SPARK for C in a lot of this article on “C’s benefits” with huge boost on safety & maintenance side. For cutting-edge, one project on 8-bit micro’s used ATS language for its combo of safety & performance. OcaPIC let’s tinkerers use Ocaml subset for algorithms if performance doesn’t preclude it. People are also getting a combo of high-level and C benefits by using DSL’s embedded in eg Haskell that output C. The Atom, Ivory, and Tower languages are examples of this. So using C doesn’t logically follow from the benefits the articles describes as other tech has them and more.

                The only thing that’s uniquely an advantage of using or mastering C in the article is understanding legacy code in popular projects. It’s mostly in C for historical & social reasons. Ability to read C is obviously helpful. One could still dodge writing it using Ada (Ada-to-C compiler) or DSL approaches above with potentially better results. Maintainers won’t accept that in popular projects, though. So, back to being able to read and write good C for this sort of thing.