What is your favourite C programming trick?
stackoverflow.com
stackoverflow.com
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. :) )
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.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).
I sometimes use "{ ... }" to limit the scope of a variable that is only needed for a small section of code.
MACRO(foo);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 :)
Once you get the big ideas, there's a very detailed reference online (http://www.lua.org/manual/5.1/), and the mailing list and wiki at 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.
long_struct_name *foo = malloc(sizeof *foo);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. #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. long_struct_name *fooArray = malloc(count * sizeof * fooArray); -->
with example code such as this: #include <stdio.h>
int main()
{
int x = 10;
while( x --> 0 ) // read "while x goes to zero"
{
printf("%d ", x);
}
}
The above code compiles and runs, listing the numbers from 9 to 0.For more details on this little known operator, I recommend this stack overflow question:
http://stackoverflow.com/questions/1642028/what-is-the-name-...
Always a classic.
#include <stdio.h>
int main() {
http://www.google.com
printf("Hello, World!");
}
(Of course, if you have syntax highlighting that label followed by a single-line comment is easier to spot.) 0 <-- x if(*(u_int32_t)cmdword == *(u_int32_t *)"EHLO") {
handle_ehlo();
}
The "extern inline" idiom for forcing inlining, which I picked up from Mike Stolarchuk.Passing and assigning trivial structures by value instead of fiddley pointers.
Arena allocators.
Not so much a trick, but: you can safely free() NULL, which saves a conditional. In the same vein: not only is there no point to casting malloc()'s return value, but there are (admittedly rare) circumstances where doing so can be harmful. So save yourself the typing.
assert(!"message") instead of assert(0).
If memory serves, CodeWarrior for Mac (and possibly other classic Mac compilers) had syntactic sugar mapping single-quoted four-character strings to the ubiquitous OSType. Something like:
OSType creatorCode = 'TTXT';
where OSType was typedef'd to uint32.But you do sometimes want to cut-paste code from .c files into .cpp files, and this idiom will make your compiler yell.
#include <stdio.h>
int foo;
int main(void)
{
struct foo {
int a, b;
} x;
printf("%zd\n", sizeof(foo));
return 0;
}
One should always write code in the best possible way for the language actually in use, even if this is invalid in some other language with superficially similar syntax. In converting code from C to C++, adding a few pointer casts will be the least of your worries.Using "extern inline" is a bad idea since no two compilers implement it the same way and none according to spec (that I know of). There is no standard way to force inlining of a function.
I also wouldn't do "extern inline" on a random C compiler; it works on clang, gcc, and Sun's compiler, though.
module_a.h: #ifndef INLINE_ # define INLINE_ inline #endif /* INLINE_ */
INLINE_ void function_a()
{
}
inline_defs.c
#define INLINE_
#include "module_a.h"You're right to point out that people should be cautious about this code. I'm just listing my "favorite tricks". I'm not recommending that people use integer casts as their go-to string comparison.
Even architectures that support misaligned accesses can be configured to trap on them and generate unexpected fatal signals.
http://stackoverflow.com/questions/328215/does-anyone-know-o...
#define CHAR4_TO_UINT(a,b,c,d) \
( \
((unsigned int)(a)) | \
( ((unsigned int)(b))<<8 )| \
( ((unsigned int)(c))<<16 )| \
( ((unsigned int)(d))<<24 ) \
)
then unsigned int ui_cmdword = CHAR4_TO_UINT(
cmdword[0], cmdword[1], cmdword[2], cmdword[3]
);
if( ui_cmdword == CHAR4_TO_UINT('H','E','L','O') )
handle_helo();
else if( ui_cmdword == CHAR4_TO_UINT('E','H','L','O') )
handle_ehlo();
А compiler will generate memory-fetching code once, optimize right side of comparisons into constants and make everything flow fast and safe. You can even use switch statement if you like.Just don't do it unless it's a quick hack that you absolutely know you'll rewrite correctly within the day, before committing. And even then, write it correctly the first time around.
This makes for a clearer code, but the conditional is still there, tucked in free's code. Obviously.
As in, specifically:
if ((Lflag ? chown : lchown)(p->fts_accpath, s->st_uid, -1))
(void)printf(" not modified: %s\n",
strerror(errno));
It was a moment of enlightenment.The corollary of this is that one should clearly document when explicitly ignoring the return value. A simple way of this in C becomes a cast to void of the return. Since printf does I/O, it qualifies.
Specifically, this code is from a patch to the FreeBSD source which is ruled by style(9); you will find this form throughout BSD source.
I see you're an old-timer here but maybe you missed out on lint: http://en.wikipedia.org/wiki/Lint_(software)
That page says it dates from the late seventies; I was still using it mid-nineties. I don't remember the last time that I linted but today Ubuntu is lint-unaware. These days the compiler will pick up most of the things that lint used to.
asprintf(s, "%s.pid", progname);
than s = malloc(strlen(progname) + 5);
strcpy(s, progname);
strcat(s, ".pid");
and it avoids errors in buffer-size computation too.(Unfortunately asprintf isn't C99; but you can construct it easily out of vsnprintf: http://code.google.com/p/libcperciva/source/browse/trunk/uti...)
Not disagreeing with you; asprintf is a good thing to have around.
Theoretically you could define an alloca()ed-pointer-returning Xsprintf as a macro, though... (but ask tptacek notes, it's probably a bad idea).
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#define SASPRINTF_MAXLEN 16
#define SASPRINTF_MERGE(a, b) a ## b
#define SASPRINTF_LEN(p) SASPRINTF_MERGE(p, _sasprintf_len)
#define SASPRINTF_BUF(p) SASPRINTF_MERGE(p, _sasprintf_buf)
#define SASPRINTF(p, fmt, ...) \
size_t SASPRINTF_LEN(p) = snprintf(NULL, 0, (fmt), __VA_ARGS__); \
char SASPRINTF_BUF(p)[SASPRINTF_LEN(p) <= SASPRINTF_MAXLEN ? SASPRINTF_LEN(p) + 1 : 0]; \
if (SASPRINTF_LEN(p) <= SASPRINTF_MAXLEN) { \
snprintf(SASPRINTF_BUF(p), SASPRINTF_LEN(p) + 1, (fmt), __VA_ARGS__); \
p = SASPRINTF_BUF(p); \
} else { \
if (asprintf(&p, (fmt), __VA_ARGS__) == -1) \
err(1, "SASPRINTF_L at %s, %d", __FILE__, __LINE__); \
}
#define SASPRINTF_FREE(p) do { \
if (p != SASPRINTF_BUF(p)) \
free(p); \
} while(0)
/* Test harness */
int main(void);
int main(void) {
char *p, *p2;
SASPRINTF(p, "%s", "foo");
SASPRINTF(p2, "%s", "Really long string, really.");
printf("%s\n%s\n", p, p2);
SASPRINTF_FREE(p);
SASPRINTF_FREE(p2);
exit(EXIT_SUCCESS);
}
I was going to say "...but you have to be pretty insane to do this", but I haven't managed to get incorrect-but-compiling code out of the above macros. Of course, I'm not at all convinced that it's faster than asprintf... (even after the obvious optimizations.)As for speed, if asprintf() does something clever to avoid rendering the string twice, this is actually slower unless snprintf() is faster than a malloc() call (unlikely). Furthermore, some compilers implement variable-length arrays with malloc() so for these, this is definitely not an improvement.
Beyond the speed of this particular call, using variable-length arrays can have a performance hit in general since gcc is unable to inline functions using them.
static cmd_handler_t handlers[16] = {
[0 ... 15] = handler_noop,
[1] = handler_for_1,
[3] = handler_for_3,
[6 ... 8] = handler_for_6_through_8
};
And suchforth. Very natural for parsers.Particularly nifty is Jaremie Miller's js0n parser, which makes heavy use of this: https://github.com/quartzjer/js0n/blob/master/js0n.c
(I see a difference between literally using GCC-dialect C and relying on dubious C constructs that happen to work well on C; for instance, I've never been bitten by "extern inline").
The problem is that the 'extern inline' gcc extension means something else, and is enabled by default unless you specify -std=c99
(Now, if only Microsoft would get off their asses and make their compiler C99-compliant, we could all write much nicer code.)
In reality, you're probably never going to see a 1's complement machine.
Your likelihood of needing to use a piece of code under a compiler other than GCC is deceptively high.
Meanwhile, the extensions we tend to think about when we think of GCC aren't subtle things like "can you use // comments in C code". They're constructs that require many additional lines of code to replace. It is a giant pain when you find them, later on, when you need to compile something under Visual C or SunWorks. Your fix to comment syntax isn't going to break code at runtime, but your fix for the missing ellipsis operator definitely can!
From bitter experience, I think 'mansr is right on this, and it's worth making an effort not to let GCC extensions creep into your code.
Sure, if you're not interested in anyone porting that code to another OS. This happens all the time with drivers -- just because the interface is OS-specific doesn't mean all the code is.
> And those extensions are there because someone likes them.
That doesn't make it a good idea.
Sacrasm aside, I like (( x > 0 )&&( (x&(x-1)) == 0 )) trick to test if x is a power of two. But all arithmetic tricks like this need to be commented in detail, used rarely, and properly documented.
Edit: I've also used "-Dfor=if(0);else for" to make some ancient C++ compiler obey C++0x scoping rules for variables declared in initializer list of 'for' statement.
char* greeting = "Hello "
"world"; #define CS_INT_SIZE(int_type) ((size_t)(0.30103 * sizeof(int_type) * 8) + 2 + 1)
int x = -1000;
char buf[CS_INT_SIZE(x)]; // instead of char buf[100];
snprintf(buf, sizeof(buf), "%d", x);
Another macro for calculating the length of a string literal in compile time (just like strlen would do). Note the extra check for string literal. #define CSLLEN(s) (sizeof(s "") - 1)
int len = CSLLEN("hello"); // len == 5 here
Another one for logging variable arguments or no arguments at all. #define Log_Trace_(...) Log(__FILE__, __LINE__, __func__, LOG_TYPE_TRACE, "" __VA_ARGS__)
void Log(const char* file, int line, const char* func, int type, const char* fmt, ...);
Log_Trace(); // prints just the name of the file, line and func
Log_Trace("Error %d", error); // prints the same as above and the error numberYou really think we'll be dealing with 512 bit integers in 40 years? This is code that's turning integers into decimal strings.
I wasn't being serious, though.
// in some header file somewhere
#define CHECK_ERROR(rc) \
if (rc != SOME_SUCCESS_VALUE) { report(rc, __FILE__, __LINE__); goto error; }
#define CHECK_MALLOC(ptr, rc) \
if (ptr == NULL) { rc = report_malloc_error(__FILE__, __LINE__); goto error; }
// in code
error_t somefunc( ... ) {
error_t rc = SUCCESS;
widget_p = make_a_widget(...);
CHECK_MALLOC(widget_p, rc);
rc = this_could_fail( ... );
CHECK_ERROR(rc);
// ...
rc = this_could_fail_too( ... );
CHECK_ERROR(rc);
return SUCCESS;
error:
// ... error clean up ...
return rc;
}
There are slight variants; like for sharing the cleanup code (e.g. "finally"), but that's the essence of it. I'm sure I've typoed something above, nit-pickers beware :-)I have a litany of reasons why you shouldn't bother checking malloc returns, and instead invest a little effort in making sure your platform malloc is configured to abort instead of returning NULL. The simplest and most compelling of those reasons is that it's easier and cleaner.
I'm also not a fan of a macro that introduces an implicit dependency on a goto label.
do { } while(0)
is a pretty convenient way of expressing single-return; you just use "break" instead of "return".I strongly disagree about the goto label. "break" is not equivalent (consider a nested for/while/switch). Plus, it's not "implicit" if it's well-known and oft-used in the code in question.
I have much stronger opinions about checking malloc. It's something people spend a lot of effort to do that actually makes their code worse.
I wish I could erase the MALLOC thing, it was an after-thought ... and now I feel like I'm leading people astray (oh well...). Even in the code that used it, it was for a existing calls that returned NULL instead of an rc. malloc() was rigged to blow in that code base. Sigh...
My habit of checking malloc() also comes from my distaste for audio software that randomly displays erratic behavior when memory starts getting tight, rather than displaying an alert that an allocation failed.
In my example above, one of the things I also failed to clarify about that test was that it was in the context of a system that could back off and restart or the call was returning NULL for reasons other than OOM. But like I said, we rigged malloc() to blow, because malloc() is the generic purpose allocator, and you're screwed if that goes.
I think tp gives good advice here: for your typical malloc() user, you're usually screwed if malloc returns NULL, because that's your heap allocator, and you have nothing else :-)
An embedded system, generally, will have a great deal more knowledge of how to back off -- in other words, the memory allocator is something that is under much more control -- it probably isn't malloc()...
p.s to the guy who down-voted my previous ( now deleted ) comment. you were right. It helped me think more precisely regarding why I was trying to crack a joke.
{
int n = 100;
char *foo = malloc(n);
...;
bar();
}
(gdb) break bar
(gdb) r
(gdb) up
(gdb) p/x *(char (*)[100]) foo
Printing malloc'd arrays can be a pain. Using the "pointer to array of type" typecast, you can force gdb to tell you everything at once. p/x *foo@100 union convert {
unsigned char ch;
struct bits {
unsigned char bit7:1;
unsigned char bit6:1;
unsigned char bit5:1;
unsigned char bit4:1;
unsigned char bit3:1;
unsigned char bit2:1;
unsigned char bit1:1;
unsigned char bit0:1;
}
}
Set the character, toggle various bits, then retrieve the character. It saves a bunch of left and right shift and or/and of values. [My C is quite rusty, so I apologize if the syntax is a bit off.]throws down gloves
"Support of the GSM 7-bit alphabet is mandatory for GSM handsets and network elements..."
type size (bits)
------------------------------
char 16
short 16
int 16
long 32
long long 40
float 32
double 32
pointer (data) 16 or 23
pointer (function) 24And... A non-function-pointer is "16 or 23" bits? Nice.
What's the proper scenario to use "long" instead of "int"? I've never bothered to use it.
It was necessary with 16-bit processors, because ints were 16-bit shorts, and longs were 32-bits.
With modern processors and OS', there isn't really a reason to use it. In fact, it's potentially dangerous if you're writing *nix code that's supposed to run on 64 or 32-bit systems. In that case, you don't want to use longs, because they're 32-bits on a 32-bit compile, but 64 on 64-bits on a 64-bit compiler. For Windows, int and long are interchangable 32-bit values, which is another reason to avoid using longs as much as possible when writing portable code.
The immediate reason is that the ALU is 40 bits wide. The reason it has this particular size is probably a tradeoff between computational power vs silicon area and power consumption.
A non-function-pointer is "16 or 23" bits?
Near and far pointers, sort of.
I had an OCD incident few years back and did a lot of thoughtful reading of all things readable on the subject. In distilled form the sacred knowledge is this - as far as the C standard is concerned, a byte is always exactly 8 bits, and a char is AT LEAST 8 bits. In fact, there is a compiler that operates in terms of 60 bit chars and that's the one on older Cray machines.
byte -- addressable unit of data storage large enough to hold any member of the
basic character set of the execution environment.
...
Note 2: A byte is composed of a contiguous sequence of bits,
the number of which is implementation-defined. #define ALIGN(type, name, align) __ALIGN_MASK(type, name, (align - 1))
#define __ALIGN_MASK(type, name, mask) char __##name##_buffer[sizeof(type) + mask];\
int * name = (type *)((size_t)(__##name##_buffer + mask) & ~mask);
Then you can just use it in the code like so: ALIGN(int, y, 16);
And you've just declared a pointer to a 16-byte aligned int on the stack. Very useful.You also violated the C standard in a less severe way. According to the standard, any identifier name starting with a double underscore (or underscore followed by upper-case letter) is reserved by the implementation for any use. These reserved names are frequently used in system header files, and encroaching on that namespace can easily lead to weird errors if the code is ever compiled on some other system.
As for the double underscore being reserved for implementation use, this was in fact part of the compiler (well, runtime in this case) implementation, again a side-effect of copy and paste.
Convert single char c into an integer:
int value = '0' - c;
Get the length of a static string you can use sizeof() instead of strlen() int len1 = sizeof("hello"); // compile-time string length
A fast and simple ring buffer (borrowed from Quake code) UPDATE_MASK = ARRAY_SIZE - 1;
array[i++ & UPDATE_MASK] = data;
Init all bits of a mask to 1 on any architecture: unsigned int flags = -1; int value = c - '0';
Otherwise, value will be negative. int value = c - '0';
Also, remember that sizeof("string") includes the null terminator while strlen() does not. typedef struct { int array[SIZE]; }Array;
Array a = {{10,16,2011}};
Array b = a;Not really a C language trick, but useful nonetheless.
#include "the_macro.h"
THE_MACRO(example, args);
and call cpp macrotest.h | fmt -w72
(using fmt since multi-line macros will end up on one line otherwise).!!foo to map 0→0 and everything else to 1. Always interesting to see if the compiler produces the best machine code for it.
I think of a trick as something only you or only few people know about regardless of how much it gets used. A technique is something that is more widely in use by people.
Had a need for it recently, and found out it was not available in C#.