
Modern C [pdf] - adamnemecek
http://icube-icps.unistra.fr/img_auth.php/d/db/ModernC.pdf
======
jws
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.

~~~
przemoc
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 2.11.7.1 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.

~~~
hawski
One of musl libc guys wrote quite convincing article about NULL:
[http://ewontfix.com/11/](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](http://www.openwall.com/lists/musl/2013/01/09/1)

~~~
przemoc
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

    
    
        (type*)0
    

or

    
    
        (type*)NULL
    

(or

    
    
        static_cast<type*>(0)
    

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

    
    
        (type*)0
    

is a good thing in this land.

Regarding musl check also:

[http://git.musl-
libc.org/cgit/musl/commit/include/stddef.h?i...](http://git.musl-
libc.org/cgit/musl/commit/include/stddef.h?id=c8a9c221)

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

    
    
        #ifdef __cplusplus
        #define NULL 0L
        #else
        #define NULL ((void*)0)
        #endif
    

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.

------
titanomachy
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.

~~~
Kliment
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.

~~~
swah
I love the internet when this happens. Thank you!

------
bjackman
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.

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

------
rifung
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.

------
pornel
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.

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

~~~
pjmlp
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

[http://channel9.msdn.com/Events/Visual-Studio/Connect-
event-...](http://channel9.msdn.com/Events/Visual-Studio/Connect-
event-2014/029)

[http://channel9.msdn.com/Events/Visual-Studio/Connect-
event-...](http://channel9.msdn.com/Events/Visual-Studio/Connect-
event-2014/311)

------
okasaki
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?

~~~
TazeTSchnitzel
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.

~~~
acqq
> 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.

~~~
TazeTSchnitzel
Ah, yes, I should've noted that.

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

------
benwaffle
there is also 21st Century C:
[http://shop.oreilly.com/product/0636920025108.do](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

~~~
Scramblejams
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.

~~~
emmanueloga_
> 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 :-).

------
swah
I enjoyed "Learn C the hard way" by Zed Shaw, but [http://hentenaar.com/dont-
learn-c-the-wrong-way](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](https://twitter.com/zedshaw/status/562535244713058304))
that the material needs a rewrite.

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

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

~~~
adamnemecek
It is a draft.

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

------
Redoubts
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](https://github.com/sarabander/sicp-
pdf) , which I find visually pleasant.

~~~
mjn
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.

------
quelsolaar
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.

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

