1. 36
  1.  

  2. 15

    I haven’t read his C guide, but I really enjoyed Beej’s Guide to Network Programming when I refactored The Last Outpost MUD for IPv6 support. He’s got a fun and informative writing style. The material is not so dumbed down as to be useless as a reference, and not so detailed as to be hard to figure out the basics. There are lots of code examples there too.

    I’d say its a nice companion to the man pages.

    1. 4

      Such was the state of C programming tutorials in 2007. Plenty of lies about heap, stack, global variables, and other made-up features not defined in the C spec. No mention of undefined behavior.

      1. 6

        But those are all terms that experienced C programmers use commonly. Anyone wanting to learn the language would need to understand this to communicate with people who already know C and have used it for years.

        Also, a lie is an intentional falsehood. Accusing someone of putting intentional falsehoods in their free tutorial seems like an unnecessarily damning accusation to throw around.

        1. 3

          I would have phrased it differently, but I think there’s a big difference between learning C programming as a concept, and then noting there are some practical implications for real world implementation, vs trying to teach a particular implementation. People who focus on “what really happens” ironically seem to make the most mistakes. More chances to go astray I think. For instance, calling static variables heap variables seems very error prone given the common advice to also free heap memory.

          1. 2

            But those are all terms that experienced C programmers use commonly. Anyone wanting to learn the language would need to understand this to communicate with people who already know C and have used it for years.

            Of course. So instead of abusing terms, what a good tutorial might do is properly explain these terms and how they relate to typical implementations of C. Having explained said terms is no excuse for not also explaining and then using actual defined C concepts such as scopes, storage durations and linkage. There’ll be fewer lies to unlearn.

          2. 1

            Where would you point people for a C tutorial relevant in 2017?

            1. 12

              I’m not aware of one I’d really want to endorse.

              “Modern C” gets more things right than your typical C tutorial – which go to the greatest lengths to avoid using standard terminology and make up their own nonsense instead. Unfortunately Modern C is also way more verbose (and makes a poor job of getting to the point) than it needs to be, and comes with plenty of dogma. It’s not entirely free of nonsense either. But it’s probably among the best of the bunch.

              http://icube-icps.unistra.fr/index.php/File:ModernC.pdf

              1. 1

                I have this one on the queue; it seems pretty clear headed. But you’re right, it is very long winded.

                1. 1

                  One approach I’ve recommended to people in the past is to just pick up whatever tutorial they need to get started with (basic syntax and concepts, a few examples), then grab a copy of the C standard drafts and just start working with real code. Look things up as you go. Read the man pages (especially from OpenBSD) for any library function you encounter. Search for dowd_ch06.pdf and read that carefully. Expert C Programming is a decent read too, once you’ve got things rolling.

                  It’ll take a while to get all the details right, but C is ultimately a fairly simple language. It shouldn’t need a huge exposition like Modern C; and if a newcomer starts by reading one, chances are they’ll forget most of the details anyway, or fail to appreciate their significance. For reference material, one might as well go straight to N1256 (or preferred version).

              2. 1

                Learn C The Hard Way, which is a paid book now :( The online version was taken down… but you can still find it

                1. 5

                  I’ve worked about a third of the way through the free version. Shaw is sort of hard to take, especially when I don’t know enough about what he writing about to judge for myself–his opinions on Python 2 vs. 3 soured me on using him as an initial tutorial for, well, pretty much anything.

            2. 2

              I would appreciate some thoughts on why people still use C in 2017. Why not use a higher level language that is capable of producing an excellent C API? Obvious candidates are C++ 17 and Rust.

              1. 23

                Well, for one thing, I don’t know any Rust and haven’t written a line of C++ in probably a decade, whereas I’ve got twenty-something years of C experience and write new code every day. :)

                There’s an awful lot of legacy C code out there that needs to be maintained.

                C is very stable: it’s changed very little over the years. I regularly work with C code that’s 30+ years old and it still compiles on modern systems with only minimal changes. Moreover, it’s relatively easy to write code today that a compiler from 30 years ago would accept. Many of the changes in subsequent C standards are aimed at increasing portability, not adding features. C++ (and Rust?) change drastically with every version, adding tons of new features.

                C is very simple: I can keep all of the semantics and all of the standard library in my head at once. Compare this to C++, where the old adage is “everyone knows about 70% of C++…it’s just that nobody knows the same 70%.” Rust and C++ are just insanely complex and huge by comparison.

                C is a “universal assembly language”: most higher level languages can easily interface with libraries written in C. You can write stuff in C++ that has a C layer on top, but things get somewhat hairier. I don’t know Rust, but I’d imagine the same sort of considerations arise there. Yes it’s “easy” to account for these things, but they still have to be accounted for.

                C is extremely portable: C compilers exist for just about any platform. This is critical when you write embedded code or code for obscure platforms.

                C has minimal runtime requirements. Yes you can write C++ (or Rust?) that targets the bare metal, but you’re going to spend at least some time on getting your runtime up.

                And finally, for me, there’s less…cognitive burden…writing C code. The fact that it’s a small language, with a small standard library helps greatly. The fact that there’s only one paradigm to consider is surprisingly helpful too. I’ve written code in C++ that needed to use stuff that couldn’t be done in an object-oriented manner and it felt…weird…because half the time I was decomposing things into classes and then half the time I wasn’t.

                (Yes I know C++ is not limited to OOP.)

                So when I write code, the general rule is I write it in Python if it’s neither low-level nor performance-critical nor needs to work standalone, and the rest I write in C. Seems to have worked well for me thus far.

                (Other tools in my toolbox include Lua, for when you need to embed a scripting language, Bourne shell because it’s everywhere and works well, make, awk, etc.)

                1. 6

                  This is all very good and true; a few small comments about Rust since you don’t know it well:

                  You can write stuff in C++ that has a C layer on top, but things get somewhat hairier. I don’t know Rust, but I’d imagine the same sort of considerations arise there.

                  Yup, you write #[no_mangle] extern fn instead of fn and you get a C ABI. Then usually you end up checking invariants, etc. It’s basically an FFI, so while it has zero cost at runtime, there’s still some work to do to write it in the first place.

                  C is extremely portable: C compilers exist for just about any platform. This is critical when you write embedded code or code for obscure platforms.

                  Rust uses LLVM, so we run into the same issues as clang there; GCC supports more platforms.

                  C has minimal runtime requirements. Yes you can write C++ (or Rust?) that targets the bare metal, but you’re going to spend at least some time on getting your runtime up.

                  Rust has basically the same amount of runtime as C does, if you want to write bare-metal code, you don’t need to do any work to get a runtime going, you say #[no_std] to turn off the standard library, and that’s pretty much it. (There is one other function you need to stub out, but hopefully you won’t even need to do that soon, and you don’t need to give a real implementation, only define the symbol.)

                  1. 2

                    Rust uses LLVM, so we run into the same issues as clang there; GCC supports more platforms.

                    I was under the impression, at least from this page, that the platforms Rust supports are a subset of those supported by LLVM, not the full set.

                    1. 4

                      Last paragraph.

                      But those aren’t the only platforms Rust can compile to! Those are the ones with built-in target definitions and/or standard library support.

                      1. 1

                        Rust is vastly over-stating its support. This statement is saying “if you work for several days, you can compile to a target!”, might as well tell me “the sky is the limit, just add a LLVM target!”.

                        I know one of the tier 2/3 targets insta-crashed if you ran anything for a long time.

                      2. 2

                        It’s true that support is not automatic, but @myfreeweb’s post does also apply too.

                        Regardless, I meant it more as an upper bound than anything else.

                  2. 12

                    I would appreciate some thoughts on why people still use C in 2017.

                    C is simple, mature, everywhere, and easy to get things done with. It doesn’t get in the way.

                    Rust and C++ in particular are ridiculously complex by comparison. Both are moving targets. There are lots of platforms Rust doesn’t run on. It’s not obvious at all why such languages should be considered obvious candidates. It’s not obvious at all that my code would meaningfully improve or that coding and maintaining it became nicer if I used Rust or C++ instead of C. I guess I could use C++ mostly as though I were writing C, but then what’s the point? It only adds more complications to deal with.

                    1. 5

                      I would appreciate some thoughts on why people still use C in 2017.

                      It’s the devil we know. Any problem you might have with it, it’s been already encountered, studied and fixed or the workarounds are documented.

                      1. 7

                        Many great comments here showing why people use C. I’m responding to this one since the point is understated. Even in high-assurance stuff at places like NASA, the developers will often choose C even if they could acquire and train on something like Ada/SPARK. The reason is there’s a tool, guide, or method to deal with about every conceivable problem. Experienced C developers will have encountered many themselves with avoidance or detection being ingrained habits. Those developers combined with that supporting ecosystem can produce more robust, efficient code than the same developers using unfamiliar language with less supporting information and tools available.

                        Now, the argument changes if they’ve had time to learn and experiment with the other language, see how it handles situations they read up on in C, and if the 80/20 rule has kicked in on tooling side where just enough exists to wipe out lots of problems. Ada is long past that point, esp if one can pay for tools. C has a FOSS advantage there. Safety-critical Java with minimal or real-time runtimes is probably next due to all the Java experience and bug-hunting tools. And, finally, Rust knocks out lots of problems with more tools and components coming online all the time. Give it a few years and tooling might be a lot better like what happened with safety-critical Java.

                      2. 5

                        Rust’s compiler is quite slow and the type system complex, C++ is the Perl of static languages. The main problems with C is the lack of safety for memory and concurrency, both of which can be mitigated by libraries and tools. I’m still using C and intend to continue doing so because it’s a simple language that lets me get close to the metal – but I only create small programs in C, otherwise the language makes it really hard to maintain the code. I admire the kernel’s developers for that.

                        1. 3

                          C++ is the Perl of static languages

                          This made me laugh aloud. ?

                        2. 3

                          In the embedded world – and it’s a pretty big world – C and assembler are the only choices right now. (Rust may have a shot, but it’s not there yet.)

                          This is mainly because of code size concerns. You need tight control over the size of the executable code and C gives you a pretty good idea of how much object code you’re going to end up with when looking at just source code. A lot of things also need careful control over the linker since, in some cases, that’s where all the work gets done. (If you’re targetting an 8-bit machine, sometimes you do all optimization in the linker, for example.)

                          There are also things like writing or placing things are precise memory locations that C facilitates without much friction.

                          1. 1

                            I find C++‘s syntax unintelligible. there’s so many single characters for higher level abstractions I don’t understand. Rust seems similar.

                          2. 1

                            Oh, hey, that’s kind of cool - that guy’s from here in Bend.