Tips For C Programming From Nic Barker

Diagram of C99 designated initializers.

If you’re going to be a hacker, learning C is a rite of passage. If you don’t have much experience with C, or if your experience is out of date, you very well may benefit from hearing [Nic Barker] explain tips for C programming.

In his introduction he notes that C, invented in the 70s by Dennis Ritchie, is now more than 50 years old. This old language still appears in lists of the most popular languages, although admittedly not at the top!

He notes that the major versions of C, named for the year they were released, are: C89, C99, C11, and C23. His recommendation is C99 because it has some features he doesn’t want to live without, particularly scoped variables and initializing structs with named members using designated initializers. Also C89 is plagued with non-standard integer types, and this is fixed by stdint.h in C99. Other niceties of C99 include compound literals and // for single-line comments.

He recommends the use of clang arguments -std=c99 to enable C99, -Wall to enable all warnings, and -Werror to treat warnings as errors, then he explains the Unity Build where you simply include all of your module files from your main.c file.

It’s stressed that printf debugging is not the way to go in C and that you definitely want to be using a debugger. To elaborate on this point he explains what a segfault is and how they happen.

He goes on to explain memory corruption and how ASAN (short for Address Sanitisation) can help you find when it happens. Then he covers C’s support for arrays and strings, which is, admittedly, not very much! He shows you that it’s pretty easy to make your own array and string types though, potentially supporting slices as well.

Finally he explains how to use arenas for memory allocation and management for static, function, and task related memory.

26 thoughts on “Tips For C Programming From Nic Barker

    1. You know, Nic Barker. He writes about C programming and other technical stuff.

      Mark Topham writes songs for Steps, a popular beat combo from the UK.

      1. Mark Topham writes a lot of songs.
        Mark Topham writes Unix books.
        Etc…

        None of which are me. The name is common enough I’ve almost run across myself directly once or twice.

        I was thinking of buying a few samples of various things made/written by Mark Topham and shoving them on a bookshelf just to see if it would trigger people; but people would misunderstand. (Thinking I’d claim authorship, instead, it just breaks first impressions and assumptions).

        I usually do web development, electronics, photography [nature, event, or astrophotography].

        Looks like this morning I’ll be a Network Engineer as I try and diagnose my wifi network so I don’t have to drive into the office.

        1. “Looks like this morning I’ll be a Network Engineer”

          So, are you going to write a song or a book about it? 😁

  1. What is a good program project for a C learner? First semester student or self teacher. Be advised that if you say “Hello World” I will invoke kanly.

    1. I often ask people to calculate a Fibonacci series using four different methods described in the comments shown below from my reference solution. It teaches them something about recursion and about runtime optimisations and how you can use approximations if you do not need precision, so not just C but also good programming practice. Apologies already for the expected presentation mess due to Hackaday formatting.

      // 1: Recursively where Fib(N) = Fib(N-1) + Fib(N-2) N ≤ 2; Fib(1) = 1; Fib(0) = 0
      // This method scales badly as each calculation of Fib(N) calls itself recursively at every step
      // and thus grows exponentially
      // Fn(N) is the number of calls required to calculate Fib(N):
      // Fn(0) 1 Fn(1) 1
      // Fn(2) 3 Fn(3) 5
      // Fn(4) 9 Fn(5) 15
      // Fn(6) 25 Fn(7) 41
      // Fn(8) 67 Fn(9) 108
      // Fn(N) ≈ 21.6^N Fn(90) ≈ 510^18
      // The runtime of the current implementation is somewhat saved by optimisation of tail recursion
      //
      // 2: Linear progression of the above formula using temporary variables to store Fib(N-1) and Fib(N-2),
      // requires N steps to calculate Fib(N)
      //
      // 3: Recursive variant of the progression with N calls of the routine to calculate Fib(N)
      //
      // 4: Calculates Fib(N) as ⎣ Phi^N / √5 + ½ ⎦ where Phi is the Golden Ratio (1 + √5)/2

  2. Great video, the only bit that would not work for me is the arena concept. It assumes large amounts of ram is available and that the scope is open for a long time. I can see it working for documents as he suggests.

      1. It can save a lot of compile time and therefore build time: If you have 60 separate compilation units and there’s a lot of the same header files imported, the C preprocessor runs 60 times as often. Building from a single .c file that #includes the remaining source files can very much decrease your build times.

  3. C99 is a good choice it is simple and good to learn with can still be used for modern software. I wouldn’t necessarily recommend newer versions unless you know what you are doing, at which point you don’t need my advice.

    1. Far too many think they know what they are doing. Most don’t understand the subtle pitfalls waiting to catch you out. Doubly so in multicore/processor systems.

      For example, consider that Hans Boehm had to forcibly point out to experts that you couldn’t write a threading library in C. Yes, experts had forgotten some of the fundamentals, and had deluded themselves that they could write threading libraries in C.

      That prodded the standards committees into inventing the memory model, something that other languages had known was necessary almost 25 years (a quarter of a century) earlier!

      I’m sceptical whether most C programmers understand the memory model and use it correctly.

      Moral: use a modern language for most purposes, leaving C for small programs.

      1. With modern coding practices you don’t need to think, but rather follow a set of precise guidelines. The worst cases of spaghetti code are usually written by independent thinker programmers, who though they are too smart to do as they’re told.

        1. Nice phrases, but there are problems when they encounter The Real World.

          “Cargo cult programmers” follow guidelines as they understand them.

          The reasons for guidelines need to be visible and to be understood, in order to avoid cargo cult programming.

          Guidelines are hints and tips based on presumptions. Guidelines cannot be comprehensive, and their quality strongly depends on the person writing the guidelines, how well they can understand their audience, and the application’s existing codebase. A language like C exacerbates those problems.

          Thinking is always necessary; there is no substitute.

          Given two imperfect tools/products, one of which makes demonstrably unrealistic presumptions about how it will be used, and one of which prevents/avoids well known misuses, which tool should a responsible engineer choose?

        2. Spaghetti code is not a symptom of thinking, it’s a symptom of a lack of planning. You ad-hoc your way through the problem and then either run out of time, money, or the will to do it properly. This is the real sin of “smart programmers”, because they tend to think as they go rather than think ahead, because they’re smart enough to do that.

          The not-so-smart programmers who follow the guidelines are better in the sense that if there’s no guidelines and no canned solutions, they just can’t do it. You get no output, but at least it’s not terrible.

        1. Looks like this is what they’re referring to: https://www.hboehm.info/misc_slides/pldi05_threads.pdf

          It just identifies a a subtle issue for multithreading that means it’s impossible for C99 to implement fully correct concurrent access to shared memory without some extra language features. Anything that synchronizes that access completely avoids the issue though, and Boehm actually commends pthread for how close it gets to full correctness.

          This isn’t a problem for 99% of developers, and it’s not like the world has imploded because of it. At worst, some people need to add extra thread synchronization that “might” not have been necessary with a different language (and it’s not like there’s a long list of alternatives listed.)

          This is also from twenty years ago. So before C11 came out.

          1. That is indeed the specific issue.

            If concurrent memory access isn’t “fully correct”, then it is incorrect. Maybe 99% of programmers don’t notice an incorrect result, or are content to reboot the application/system, but not all of us are in that position. Some of us write life critical programs.

            Later versions of C have addressed the problem, but the standards committee members (?experts?) should have noticed the problem decades earlier and corrected the omission.

            For those that fancy themselves expert C programmers, there’s always the drolly amusing C++ FQA to calibrate their belief https://yosefk.com/c++fqa/ . Many of the infelicities noted for C++ are equally valid in C.

  4. Also would like to recommend the usage of static code analysers. I use cppcheck myself with the GUI. Its easy to use and catches a lot of stuff (mostly edge cases that you might have missed)

Leave a Reply to OraclesCancel reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.