Alex Rivera | Logout

What is your favorite C programming trick?

Asked 2009-03-01T06:21:09.363
134

For example, I recently came across this in the linux kernel:

/* Force a compilation error if condition is true */
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))

So, in your code, if you have some structure which must be, say a multiple of 8 bytes in size, maybe because of some hardware constraints, you can do:

BUILD_BUG_ON((sizeof(struct mystruct) % 8) != 0);

and it won't compile unless the size of struct mystruct is a multiple of 8, and if it is a multiple of 8, no runtime code is generated at all.

Another trick I know is from the book "Graphics Gems" which allows a single header file to both declare and initialize variables in one module while in other modules using that module, merely declare them as externs.

#ifdef DEFINE_MYHEADER_GLOBALS
#define GLOBAL
#define INIT(x, y) (x) = (y)
#else
#define GLOBAL extern
#define INIT(x, y)
#endif

GLOBAL int INIT(x, 0);
GLOBAL int somefunc(int a, int b);

With that, the code which defines x and somefunc does:

#define DEFINE_MYHEADER_GLOBALS
#include "the_above_header_file.h"

while code that's merely using x and somefunc() does:

#include "the_above_header_file.h"

So you get one header file that declares both instances of globals and function prototypes where they are needed, and the corresponding extern declarations.

So, what are your favorite C programming tricks along those lines?

c
Edit
Report

4 Answers

67

While reading Quake 2 source code I came up with something like this:

double normals[][] = {
  #include "normals.txt"
};

(more or less, I don't have the code handy to check it now).

Since then, a new world of creative use of the preprocessor opened in front of my eyes. I no longer include just headers, but entire chunks of code now and then (it improves reusability a lot) :-p

Thanks John Carmack! xD

answered 2009-11-02T16:12:48.993
50

I'm fond of using = {0}; to initialize structures without needing to call memset.

struct something X = {0};

This will initialize all of the members of the struct (or array) to zero (but not any padding bytes - use memset if you need to zero those as well).

But you should be aware there are some issues with this for large, dynamically allocated structures.

answered 2009-03-01T11:03:50.213
22

I like the "struct hack" for having a dynamically sized object. This site explains it pretty well too (though they refer to the C99 version where you can write "str[]" as the last member of a struct). you could make a string "object" like this:

struct X {
    int len;
    char str[1];
};

int n = strlen("hello world");
struct X *string = malloc(sizeof(struct X) + n);
strcpy(string->str, "hello world");
string->len = n;

here, we've allocated a structure of type X on the heap that is the size of an int (for len), plus the length of "hello world", plus 1 (since str1 is included in the sizeof(X).

It is generally useful when you want to have a "header" right before some variable length data in the same block.

answered 2009-03-01T07:34:27.470
0

I love empty if-else and while(0) operators.

For example:

#define CMD1(X) do { foo(x); bar(x); } while (0)
#define CMD2(X) if (1) { foo(x); bar(x); } else
answered 2011-10-17T05:57:29.337

Your Answer