Hacker News new | past | comments | ask | show | jobs | submit login
Modern C [pdf] (unistra.fr)
250 points by adamnemecek on Feb 8, 2015 | hide | past | web | favorite | 43 comments

I might have to make a What has changed in C since 1980 page for old programmers. I've tried to stay current, but I learned something from this book already:

    size_t strlen(char const string[static 1]); 
    int main(int argc, char* argv[argc+1]);
This allegedly helps prevent null pointers from being passed in, and presumably tells the analyzers and optimizers some things they should know.

It's worth a look at C11 as well, some of what you might have used gcc or clang attributes for has climbed into the language, such as _Noreturn, _Alignas, _Alignof and their friend aligned_alloc().

Addendum: Well, you can pass in pointers that go to fewer elements, but you can't pass in an actual naked null.

I didn't know about use of static keyword in array parameter declaration, but I dare to say that a lot of senior C programmers are unaware of this C99 feature.

It's nice to be able to specify function's expectations on that level, yet it looks that only clang (tested with 3.5.0) takes use of it, while gcc (tested with 4.9.1) seems oblivious to it. Be it NULL or shorter string literal than expected, gcc with -Wall -Wextra -pedantic -std=c99 spits nothing. Both mistakes are detected by clang.

Sadly even clang doesn't warn us when fun(int len, char str[static len+1]) is called like fun(5, "test").

But I'm not sure that I agree with the rule Don't use NULL. In any sane C environment NULL is defined as follows (unless __cplusplus is already defined, because then it's defined as 0 or 0L)

    #define NULL ((void*)0)
and IMHO there is nothing wrong with that.

Distinguishing kind of 0 we're dealing with (even if it's not strongly guarded by compiler) is often important for readability and eases maintenance of the code (0 vs '\0' vs NULL). While comparing pointer with NULL (writing p == NULL or p != NULL instead of simply !p or p) may seem superfluous (yet I have nothing against programmers doing so), calling function with pointer parameters providing 0 argument instead of NULL seems less clear to me.

> if you really want to emphasize that the value is a pointer use the magic token sequence (void *)0 directly.

I don't buy it.

One of musl libc guys wrote quite convincing article about NULL: http://ewontfix.com/11/

There was also discussion on musl mailing list (I don't know is this best link to it): http://www.openwall.com/lists/musl/2013/01/09/1

The topic was modern C and in modern C environment NULL is defined as

    (void *)0
There is no point in writing longer form and it's still clearer and safer than 0 alone.

C++ is another story with its

    void* hate
built-in. In this land you rather write



for extra purists), but as you're denoting pointer type already in this notation, there is not much gain in using NULL instead of 0 (well, beside grepability).

In many cases you can be done with 0 alone in C++, that's true, and in such cases NULL at least poses some intention, but if you're not careful enough, you may end up putting NULL alone (without pointer-to-type cast) in some variadic function and things start to blow up all of a sudden (that is if your NULL integer width isn't the same as pointer width). That's why having a habit of writing

is a good thing in this land.

Regarding musl check also:


In short, musl's stddef.h has following lines:

    #ifdef __cplusplus
    #define NULL 0L
    #define NULL ((void*)0)
NULL defined as 0L for C++ is nice workaround, but it works only for LP64 platforms.

In the same vein for Windows C++ x64 environment you need NULL to be 0LL, as it is LLP64 platform.

Please do. I learnt C in the late 80s from rather old materials and am not fluent in the modern style. While I can "read" C mostly OK, I feel a bit like Shakespeare trying to read Snoop Dogg lyrics at the best of times. I should just invest the time to relearn C from scratch, but a primer on the changes would at least get the fire burning again.

Please have a native English speaker edit this book before distributing it. It'd be a shame to have such substantial work dismissed due to awkward use of language.

I've just emailed the author offering to proof/edit. I used to do copy editing in a past life.

Update: He wrote back and agreed.

I love the internet when this happens. Thank you!

Though the English is pretty good through most of it, there's just one or two rough spots.

Could you provide examples for a non-native English speaker? This is really interesting to me, I have not encountered obvious (for me) mistakes in the book yet, so it's a learning opportunity.

Couple of things:

- Pages 156 to 164 are missing (I tried to skip straight to the "Ambition" section but couldn't find it).

- The first sentence, "It has been a long time since the programming language C is around" sounds wrong to a native English speaker. Say "The C programming language has been around for a long time" or "It has been a long time since the C programming language appeared". "Since" in English generally refers to things that happened in perfect tenses (as opposed to e.g. "depuis" in French that has an imperfect tone).

Hope these are helpful. Book sounds great.

Only the first 3 sections have been written, so the other stuff is coming later.

This looks awesome, I haven't had the need to become more proficient at C since having learned (the basics of ) it as my first language, but this gives me some motivation to learn more about it.

I also really like that the book can be read by people of varying levels of experience, with sections devoted to different groups.

I really like C99. I've been trying to write C like that and the only problem is that there are some users who really like their MSVC from 1998 that doesn't support half of that book.

You mean their MSVC from 2012. They only just added support for C99 with the latest release.

Because C is legacy on Windows. No need for C when there is C++, which also allows for safer systems programming.

The C99 subset that was added was what is required by C++11/C++14 standards and some key customers.

There are no plans for full ANSI C compliance, as discussed here



They added some support for C99. It is still missing bunch of stuff. Like "static" in array parameter index.

and even then, I think their implementation of complex.h is screwball.

Using unsigned ints everywhere seems like bad advice. Years may always be non-negative, but year1 - year2 won't be half the time.

And if it's modern C, why not use the typedefs from stdint.h?

If your result can be negative, use a signed integer. But in many cases you shouldn't: unsigned integers have well-defined behaviour, you should take advantage of that.

Also, while it's true that modern C has the stdint.h typedefs, the old types are still good. All of the standard library, and many libraries you use, use the old types, so this makes interaction with them more practical. Furthermore, it'd probably best to use sizes suited to your platform. A long will be 32-bit on a 32-bit system and 64-bit on a 64-bit system. You only need long long in some cases. You can't avoid the traditional C types for things like strings, either.

Really, stdint.h only matters if you're reading binary data or performance is ultra-important, IMO.

Signed integers have undefined overflow, but unsigned integers underflow really easily.

IMO unsigned integers shouldn't have a subtraction operator named '-'. The semantics are sufficiently different that a subtraction operation on unsigneds should stand out.

(I am not a fan of using unsigned integers for semantically non-negative numbers. They are not simply a non-negative bounded type; they are a different type of integer, with a different arithmetic not familiar to everyday maths. But this is a tough row to hoe in C. Other languages, like Java and C#, didn't inherit the same mistake.)

How often is overflow a concern, especially on 64bit?

Probably not as often as you use subtraction.

Plus, gcc has -fsanitize=signed-integer-overflow.

> A long will be 32-bit on a 32-bit system and 64-bit on a 64-bit system.

Not on Windows. Long is there always 32 bits.

Ah, yes, I should've noted that.

"Rule A C and C++ are different, don’t mix them and don’t mix them up." :D

there is also 21st Century C: http://shop.oreilly.com/product/0636920025108.do

half of it is about tools (valgrind, make, autoconf) and it also talks about libraries (sqlite, gsl, etc...) of course there are some chapters about the language itself

How did you like that book? I was thinking about buying it, but a number of the reviews I read dampened my enthusiasm.

FWIW tptacek likes C Interfaces and Implementations by Hanson, wonder how that compares.

> I was thinking about buying it, but a number of the reviews I read dampened my enthusiasm.

A bit meta:

Looking for a book in a particular subject, I picked one because of a number of the reviews I read, but actually reading the book dampened my enthusiasm.

I don't know about this particular book, but if the subject is worth it it is probably also worth your time to check it out yourself :-).

Personally, I liked the book, but what the parent comment said about its contents is true. Half is tools, then the rest is mostly libraries, and then there is some stuff on the language. But if you didn't know about those things to begin with, then its very helpful.

I enjoyed "Learn C the hard way" by Zed Shaw, but http://hentenaar.com/dont-learn-c-the-wrong-way kinda opened my eyes for some issues, and Zed seems to aggree (https://twitter.com/zedshaw/status/562535244713058304) that the material needs a rewrite.

I can't seem to copy/paste the code examples without it messing up the formatting. Can this be resolved?

Is this a draft ? Section on Reetrancy seems to be missing ?

It is a draft.


Read it again. He explicitly says "You may well share this by pointing others to my home page or one of the links above" which is what this post does.

My mistake. I'll delete the comment.

That just means link to his website and don't rehost / share by email etc. He says you can share the link.

The book doesn't render properly in FF (but in Adobe Reader).

I hate to be that guy, but I find the formatting very off putting -- especially with respect to the internal links. Compare to https://github.com/sarabander/sicp-pdf , which I find visually pleasant.

The internal links framed by a colored box are the default rendering of the LaTeX hyperref package. I also don't like them, but they seem to be pretty common, e.g. most arXiv papers do that. You can turn it off by passing the 'hidelinks' parameter when loading the package.

In addition to those hyperref settings, the code typography could be much improved. It features multiple fonts, colors and weights. I would use a single monospace font, with only a gray/black contrast for highlighting. Easier on the eyes and would look more professional.

I agree. The document is visually bad designed. Can't read it. Someone toss the author some LaTeX?

The book claims that integer numbers wrap around. Thats not strictly true. According to the C spec the overflow behavior is undefined, how ever on all hardware known to man it wraps around. Why does it matter? Because some compilers may assume no wrap around ever happens and use this to optimize.

It only claims that for unsigned integers, which is true. It also correctly says that signed overflow is undefined.

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