since the variable type info is already statically available. That saves some typing, and (more importantly) blocks against bugs from changing one but not the other. I've been meaning to look it up in H&S to make sure it's always safe, but the guy who showed it to me is so strict about safe/standard C that it's likely.
Most of my favorite tricks actually involve the preprocessor, though. I know it's significantly less expressive than the macro systems in Lisp, Scheme, or OCaml, but C would be a very different language without it, and tasteful CPP usage can ease many of C's pain points.
(My other other favorite C programming trick is knowing Lua, which is excellent for scripting C. :) )
(My other other favorite C programming trick is knowing Lua, which is excellent for scripting C. :) )
I especially love LuaJIT, whose ffi makes it even easier to interface with C than standard Lua does (and its awesomely fast too). Nevermind that Lua is just nice to work in anyway :)
The best book for Lua by a longshot is Roberto Ierusalimschy's _Programming in Lua_, second ed. (http://www.inf.puc-rio.br/~roberto/pil2/) It covers the core language and the C API with the same clear, erudite treatment as K&R. (He is one of the core Lua authors.)
Lua is transitioning from 5.1 to 5.2 right now, which introduces some changes (improvements to the GC, adding to the standard libraries, and improving the package/module system). The main language and C API haven't changed significantly from 5.1; you should be fine if you learn 5.1 now and update later. Lua is small enough that you could add 5.1 to your projects as a library dependency and maintain it yourself, though - it's only about 16,000 lines of code.
Variables are in scope in their own initializers. This is fun when you inadvertently write something like:
int length = ...;
...more code, lose your concentration...
if(x) {
int length = length / 2 + 1;
...
}
This neither produces an error nor does what you'd expect, but just ends up being a creative way to initialize the inner length variable with garbage. I've done this more than I care to admit.
Definitely. Know your warning options! Also, try using multiple compilers. tcc compiles very quickly, clang often has better error messages, etc.
Speaking of variable shadowing: It's usually worth wrapping any preprocessor macros in a "do { ... } while (0)" block unless you deliberately want variable definitions to escape (in which case, token pasting a suffix is usually a good idea).
That is a gcc extension. The construct as a whole has the value of the last statement executed within. Usually an inline function is preferable since it achieves the same thing using only standard syntax.
Would be nice if there was one which would warn for this specific case but not shadowing in general, which I occasionally like. (This probably makes me a bad person.)
It certainly doesn't make you a bad person. If lexical scoping wasn't the intent of the language authors, it wouldn't exist. I tend to agree that the warning is more of a hassle than it's worth. Though I guess it can be argued that if your scoping is so deep that you actually need to reuse names, that perhaps some refactoring should be in order.
Seeing a variable shadow something in an outer scope makes me cringe, simply because the decrease in readability far outweighs any benefit it could give. You might remember how things are, but the poor sap who has to keep extra scoping depths in his mind just to maintain your code will curse your name every day.
If a type name is used, it always needs to be enclosed in parentheses, whereas variable names and expressions can be specified with or without parentheses.
Similarly with NEW0() and ecalloc(). Yes, the macro uses the parameter more than once, and yes it's another macro for the reader to grasp, but it's a simple one and NEW() is used so widely it's soon learnt.
Most of my favorite tricks actually involve the preprocessor, though. I know it's significantly less expressive than the macro systems in Lisp, Scheme, or OCaml, but C would be a very different language without it, and tasteful CPP usage can ease many of C's pain points.
(My other other favorite C programming trick is knowing Lua, which is excellent for scripting C. :) )