6 ms·
Recently, I learned that instead of saying long_struct_name *foo = malloc(sizeof(long_struct_name)); you can say long_struct_name *foo = malloc(sizeo
by silentbicycle 15y ago
Recently, I learned that instead of saying
long_struct_name *foo = malloc(sizeof(long_struct_name));
you can say
long_struct_name *foo = malloc(sizeof(*foo));
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. :) )
- tptacek 15y agoIt's always safe, and is also the correct way to write the expression.
- deleted 15y ago[deleted]
- mikeash 15y agoVariables 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.
- pagekalisedown 15y agoIf you're using gcc, you can compile with "-Wshadow" to get a warning for this type of problem. See: http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
- silentbicycle 15y agoDefinitely. 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).
- AlexandrB 15y agoIsn't "do { ... } while (0)" the same as just "{ ... }"? I sometimes use "{ ... }" to limit the scope of a variable that is only needed for a small section of code.
- enqk 15y agodo { ... } while (0) makes your macro behave like a statement (i.e. the semicolon is mandatory)
- rcfox 15y ago({ ... }) does this too. (Is this GCC-specific?)
- mansr 15y agoThat 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.
- silentbicycle 15y agoYes. I don't include the trailing semicolon in macro definitions, because I expect the macro to be followed by them: MACRO(foo);
- huhtenberg 15y ago
- dkersten 15y ago(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 :)
- ecounysis 15y agoWhere would one start learning to script C with Lua?
- silentbicycle 15y agoThe best book for Lua by a longshot is Roberto Ierusalimschy's _Programming in Lua_, second ed. (http://www.inf.puc-rio.br/~roberto/pil2/ 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.) Once you get the big ideas, there's a very detailed reference online (http://www.lua.org/manual/5.1/ http://www.lua.org/manual/5.1/), and the mailing list and wiki at http://lua-users.org/ http://lua-users.org/ also have a lot of helpful info. 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.
- decklin 15y agoAlso, sizeof is an operator, not a function, so you can write that as long_struct_name *foo = malloc(sizeof *foo);
- tkahn6 15y agoThis is true but there is a qualifier here: 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. So long_struct_name *foo = malloc(sizeof long_struct_name) won't compile.
- ralph 15y agoTo avoid the duplication, with risk of mismatch, and to make it one less thing for the reader to check, I have #define NEW(a) ((a) = emalloc(sizeof(*(a)))) NEW(foo); 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.
- kpreid 15y agoIndeed this is good style. The following, however, is not good style for allocating an array: long_struct_name *fooArray = malloc(count * sizeof * fooArray);