What is your favorite C programming trick?

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?


C99 offers some really cool stuff using anonymous arrays:

Removing pointless variables

{
    int yes=1;
    setsockopt(yourSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
}

becomes

setsockopt(yourSocket, SOL_SOCKET, SO_REUSEADDR, (int[]){1}, sizeof(int));

Passing a Variable Amount of Arguments

void func(type* values) {
    while(*values) {
        x = *values++;
        /* do whatever with x */
    }
}

func((type[]){val1,val2,val3,val4,0});

Static linked lists

int main() {
    struct llist { int a; struct llist* next;};
    #define cons(x,y) (struct llist[]){{x,y}}
    struct llist *list=cons(1, cons(2, cons(3, cons(4, NULL))));
    struct llist *p = list;
    while(p != 0) {
        printf("%dn", p->a);
        p = p->next;
    }
}

Any I'm sure many other cool techniques I haven't thought of.


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


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.

链接地址: http://www.djcxy.com/p/12774.html

上一篇: 混淆C代码大赛2006年。请解释sykes2.c

下一篇: 你最喜欢的C编程技巧是什么?