Modern C [pdf]
icube-icps.unistra.fr
icube-icps.unistra.fr
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.
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.
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
(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...
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.
Update: He wrote back and agreed.
- 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.
I also really like that the book can be read by people of varying levels of experience, with sections devoted to different groups.
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-...
And if it's modern C, why not use the typedefs from stdint.h?
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.
Not on Windows. Long is there always 32 bits.
Probably not as often as you use subtraction.
Plus, gcc has -fsanitize=signed-integer-overflow.
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.)
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
FWIW tptacek likes C Interfaces and Implementations by Hanson, wonder how that compares.
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 :-).