views:

4256

answers:

27

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?

+2  A: 

Rusty actually produced a whole set of build conditionals in ccan, check out the build assert module:

#include <stddef.h>
#include <ccan/build_assert/build_assert.h>

struct foo {
        char string[5];
        int x;
};

char *foo_string(struct foo *foo)
{
        // This trick requires that the string be first in the structure
        BUILD_ASSERT(offsetof(struct foo, string) == 0);
        return (char *)foo;
}

There are lots of other helpful macros in the actual header, which are easy to drop into place.

I try, with all of my might to resist the pull of the dark side (and preprocessor abuse) by sticking mostly to inline functions, but I do enjoy clever, useful macros like the ones you described.

Tim Post
Yeah, I recently came across ccan, and was considering contributing some code, but haven't yet wrapped my head around the "ccan way."Thanks for the link though, more motivation to look into ccan, which I really hope gets some traction.
smcameron
Well, I would not get too concerned on the 'ccan way' until its more established ... right now ccan-lint is being proposed as a GSOC project. Its a small and rather friendly group .. and a great place to dump snippets :)
Tim Post
BTW, I noticed Rusty's BuILD_ASSERT is just like the macro from the linux kernel (unsurprising) but lacking one of the "nots" (or bangs, or !'s) and noticing that, I think my example usage of the macro I posted is not correct. Should have been: "BUILD_BUG_ON((sizeof(struct mystruct) % 8))"
smcameron
+6  A: 

Another nice pre-processor "trick" is to use the "#" character to print debugging expressions. For example:

#define MY_ASSERT(cond) \
  do { \
    if( !(cond) ) { \
      printf("MY_ASSERT(%s) failed\n", #cond); \
      exit(-1); \
    } \
  } while( 0 )

edit: the code below only works on C++. Thanks to smcameron and Evan Teran.

Yes, the compile time assert is always great. It can also be written as:

#define COMPILE_ASSERT(cond)\
     typedef char __compile_time_assert[ (cond) ? 0 : -1]
Gilad Naor
The COMPILE_ASSERT macro can't be used twice though, as it pollutes the namespace with a typedef, and the 2nd usage gets: error: redefinition of typedef ‘__compile_time_assert’
smcameron
Did you actually try this?You can "typedef foo;" as many times as you like. That's how you do predeclarations. I've used it for 2.5 years now on several compilers, both gcc, VC and a compiler for an embedded environment, and never encountered any difficulties.
Gilad Naor
I hate the C preprocessor ... :(
hasen j
Yes, I tried it. I cut and pasted the error message from the compiler, which was gcc.
smcameron
I would cut and past the code, but the "comments" are so limited here since the goofballs who run this site don't want actual discussion, but instead are obsessed with "questions" and "answers."
smcameron
COMPILE_ASSERT(1);COMPILE_ASSERT(1);int main(int argc, char *argv[]){ printf("hello world\n")'}(see if that fits.)
smcameron
@Gilad: it is legal in c++ to have redundant typedefs, but not in c.
Evan Teran
Okay, I stand corrected. Another thing learned today.
Gilad Naor
+2  A: 

Two good source books for this sort of stuff are The Practice of Programming and Writing Solid Code. One of them (I don't remember which) says: Prefer enum to #define where you can, because enum gets checked by the compiler.

Yuval F
AFAIK, in C89/90 there is NO typechecking for enums. enums are just somehow more convenient #defines.
cschol
+24  A: 

If we are talking about c tricks my favourite has to be Duff's Device for loop unrolling! I'm just waiting for the right opportunity to come along for me to actually use it in anger...

Jackson
Yeah, Duff's device is a good one. Never had a chance to use it in practice myself, but can appreciate the, uh, "beauty" of it.
smcameron
I've used it once to produce a measurable performance gain, but these days it's not useful on a lot of hardware. Always profile!
Dan Olson
Last time I mentioned Duff's Device I got serious downvoted! :)
Mitch Wheat
^^ yeah, I was tempted to downvote this, too. Duff's Device is definitely cool, but it epitomizes microptimization at the cost of code readability.
Nik Reiman
While it may be a micro-optimisation, in the context of *this* question it seems a perfect answer.
Richard
I seem to have garnered 1 downvote for every two upvotes on this! Is there a secret 'we hate duff's device' society lurking on stack overflow? :-)
Jackson
Yeah, the sort of people who don't understand the context Duff's device was created in: "code readability" is useless if the code is not fast enough to work. Probably none of the people who downvoted you have ever had to code for hard realtime.
Rob K
+1, I have actually needed to use Duff's device a few times. The first time was a loop that basically just copied stuff and did some small transformation on the way. It was much, much faster than a simple memcpy() in that architecture.
Makis
The anger will be from your colleagues and successors who have to maintain your code after you.
Jonathan Leffler
As I said, I am still waiting for the right opportunity - but no one has annoyed me enough yet. I have been writing C for about 25 years now, I think I first came across Duff's device in the early 90s and I have not had to use it yet. As others have commented this kind of trick is less and less useful now as compilers get better at this kind of optimization.
Jackson
+15  A: 

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 str[1] 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.

Evan Teran
I personally find it easier to just malloc() and realloc() myself and use strlen() whenever I need to find the length, but if you need a program that never knows the length of the string and will likely need to find it many times, this is probably the better road.
Chris Lutz
"... the C99 version where you can write "str[]""I've seen zero sized arrays in such a context, like str[0]; fairly often. I think it's C99. I know older compilers complain about zero sized arrays though.
smcameron
What I like about the char[1] is it handles the 0-byte at the end of the string for you. There's no additional +1 in the malloc.
jmucchiello
I use this too, and it's beautiful. +1.
strager
I like this one as well, however, you should use something like *malloc(offsetof(X, str) + numbytes)* otherwise things will go wrong because of padding and alignment issues. E.g. sizeof(struct X) might be 8, not 5.
Fozi
@Fozi: I actually don't think that would be a problem. Since this version has `str[1]` (not `str[]`) the 1 byte of str is included in the `sizeof(struct X)`. This **includes** any padding between `len` and `str`.
Evan Teran
+2  A: 

I wouldn't really call it a favorite trick, since I've never used it, but the mention of Duff's Device reminded me of this article about implementing Coroutines in C. It always gives me a chuckle, but I'm sure it could be useful some time.

Dan Olson
A: 

I don't know if it's a trick. But when I was a junior in university a friend of mine and I were completing a lab in our intro C++ course. We had to take a person's name and capitalize it, display it back, and then give them the option of displaying their name "last, first". For this lab we were prohibited from using array notation.

He showed me this code, I thought it was the coolest thing I'd seen at the time.

char * ptr = "first name";

//flies to the end of the array, regardless of length
while( *ptr++ );
Chris
white -> while
Learning
In your example, you can no longer reliably go back to the beginning of your array. It would make more sense to declare a second char *, initially pointing to the same place as ptr, but increment this second char * instead.
dreamlax
Yes, there is more code obviously.
Chris
Hopefully so -- so far this code does nothing worthy...
Leonardo Herrera
+2  A: 

See "Hidden features of C" question.

Alex B
+16  A: 

Once a mate of mine and me redefined return to find a tricky stack corruption bug.

Something like:

#define return DoSomeStackCheckStuff, return
Andrew Barrett
Hopefully that was #define'd in the function body and #undefine'd at the end!
strager
+4  A: 
#if TESTMODE == 1    
    debug=1;
    while(0);     // Get attention
#endif

The while(0); has no effect on the program, but the compiler will issue a warning about "this does nothing", which is enough to get me to go look at the offending line and then see the real reason I wanted to call attention to it.

gbarry
couldn't you use #warning instead ?
Stefano Borini
Apparently, I could. It's not completely standard, but it worked in the compilers that I use. Interestingly, the embedded compiler translated a #define, while gcc did not.
gbarry
+4  A: 

This one comes from the book 'Enough rope to shoot yourself in the foot':

In the header declare

#ifndef RELEASE
#  define D(x) x
#else
#  define D(x)
#endif

In your code place testing statements eg:

D(printf("Test statement\n"););

(I tend to include the last semicolon as well so emacs will indent it properly)

The statement will only be printed if '-D RELEASE' flag for compiler is not used.

You can then eg. pass the flag to your makefile etc.

Not sure how this works in windows but in *nix it works well

Simon Walker
You might want to expand D(x) to {} when RELEASE is defined, so that it plays nice with if statements. Otherwise "if (a) D(x);" will expand to just "if (a)" when you have RELEASE defined. That will give you some nice bugs in the RELEASE verison
MarkJ
@MarkJ: NO. The way it is, "if(a) D(x);" expands to "if(a);" which is perfectly fine. If you had D(x) expand to {}, then "if(a)if(b)D(x);else foo();" would INCORRECTLY expand to "if(a)if(b){};else foo();", causing the "else foo()" to match with the second if instead of the first if.
Adam Rosenfield
To be honest i mostly use this macro for testing print statements, or if i had a conditional statement i would enclose it all eg. D(if(a) foo(););
Simon Walker
Enough rope indeed.
Matt B.
+20  A: 

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.

therefromhere
Not needed for global variables, by the way.
strager
Not needed for _static_ variables. Global variables may be zeroed, but it's not a requirement.
Jamie
I sometimes extend this to: `const struct something zero_something = { 0 };` and then I can reset a variable on the fly with `struct something X = zero_something;` or part-way through a routine I can use 'X = zero_something;'. The only possible objection is that it involves reading data from somewhere; these days, a 'memset()' might be quicker - but I like the clarity of the assignment, and it is also possible to use other-than-zero values in the initializer too (and memset() followed by tweaks to individual member may be slower than a simple copy).
Jonathan Leffler
+7  A: 

Object oriented code with C, by emulating classes.

Simply create a struct and a set of functions that take a pointer to that struct as a first parameter.

Brian R. Bondy
Is there still something out there that translates C++ into C, like cfront used to?
MarkJ
+7  A: 

Bit-shifts are only defined up to a shift-amount of 31 (on a 32 bit integer)..

What do you do if you want to have a computed shift that need to work with higher shift-values as well? Here is how the Theora vide-codec does it:

unsigned int shiftmystuff (unsigned int a, unsigned int v)
{
  return (a>>(v>>1))>>((v+1)>>1);
}

Or much more readable:

unsigned int shiftmystuff (unsigned int a, unsigned int v)
{
  unsigned int halfshift = v>>1;
  unsigned int otherhalf = (v+1)>>1;

  return (a >> halfshift) >> otherhalf; 
}

Performing the task the way shown above is a good deal faster than using a branch like this:

unsigned int shiftmystuff (unsigned int a, unsigned int v)
{
  if (v<=31)
    return a>>v;
  else
    return 0;
}
Nils Pipenbrinck
... and gcc actually inlines it :) +1
Tim Post
On my machine, gcc-4.3.2 gets rid of the branch in the second one by using a cmov instruction (conditional move)
Adam Rosenfield
+11  A: 

using __FILE__ and __LINE__ for debugging

#define WHERE fprintf(stderr,"[LOG]%s:%d\n",__FILE__,__LINE__);
Pierre
On some compilers you get __FUNCTION__ as well.
JBRWilkinson
+6  A: 

Using a stupid macro trick to make record definitions easier to maintain.

#define COLUMNS(S,E) [(E) - (S) + 1]

typedef struct
{
    char studentNumber COLUMNS( 1,  9);
    char firstName     COLUMNS(10, 30);
    char lastName      COLUMNS(31, 51);

} StudentRecord;
EvilTeach
+1  A: 

I think the use of userdata pointers is pretty neat. A fashion losing ground nowdays. It's not so much a C feature but is pretty easy to use in C.

epatel
I wish that I understood what you meant here. Could you explain more? What is a userdata pointer?
Zan Lynx
Plz see here http://stackoverflow.com/questions/602826/what-is-a-good-definition-of-a-userdata-pointer
epatel
it's primarily for callbacks. It is some data you would like to be given back to you each time the callback is fired. Particularly useful for passing a C++ this pointer to a callback so you can tie an object to an event.
Evan Teran
Ah, yes. Thanks. I use this a lot, but I have never called it that.
Zan Lynx
+8  A: 

In C99

typedef struct{
    int value;
    int otherValue;
} s;

s test = {.value = 15, .otherValue = 16};

/* or */
int a[100] = {1,2,[50]=3,4,5,[23]=6,7};
Jasper Bekkers
+6  A: 

For creating a variable which is read-only in all modules except the one it's declared in:

// Header1.h:

#ifndef SOURCE1_C
   extern const int MyVar;
#endif


// Source1.c:

#define SOURCE1_C
#include Header1.h // MyVar isn't seen in the header

int MyVar; // Declared in this file, and is writeable


// Source2.c

#include Header1.h // MyVar is seen as a constant, declared elsewhere
Steve Melnikoff
+4  A: 

Declaring array's of pointer to functions for implementing finite state machines.

int (* fsm[])(void) = { ... }

The most pleasing advantage is that it is simple to force each stimulus/state to check all code paths.

In an embedded system, I'll often map an ISR to point to such a table and revector it as needed (outside the ISR).

Jamie
+1  A: 

I use X-Macros to to let the pre-compiler generate code. They are especially useful for defining error values and associated error strings in one place, but they can go far beyond that.

JayG
+18  A: 

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("%d\n", p->a);
     p = p->next;
    }
}

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

Evan Teran
A: 

Here is an example how to make C code completly unaware about what is actually used of HW for running the app. The main.c does the setup and then the free layer can be implemented on any compiler/arch. I think it is quite neat for abstracting C code a bit, so it does not get to be to spesific.

Adding a complete compilable example here.

/* free.h */
#ifndef _FREE_H_
#define _FREE_H_
#include <stdio.h>
#include <string.h>
typedef unsigned char ubyte;

typedef void (*F_ParameterlessFunction)() ;
typedef void (*F_CommandFunction)(ubyte byte) ;

void F_SetupLowerLayer (
F_ParameterlessFunction initRequest,
F_CommandFunction sending_command,
F_CommandFunction *receiving_command);
#endif

/* free.c */
static F_ParameterlessFunction Init_Lower_Layer = NULL;
static F_CommandFunction Send_Command = NULL;
static ubyte init = 0;
void recieve_value(ubyte my_input)
{
    if(init == 0)
    {
     Init_Lower_Layer();
     init = 1;
    }
    printf("Receiving 0x%02x\n",my_input);
    Send_Command(++my_input);
}

void F_SetupLowerLayer (
    F_ParameterlessFunction initRequest,
    F_CommandFunction sending_command,
    F_CommandFunction *receiving_command)
{
    Init_Lower_Layer = initRequest;
    Send_Command = sending_command;
    *receiving_command = &recieve_value;
}

/* main.c */
int my_hw_do_init()
{
    printf("Doing HW init\n");
    return 0;
}
int my_hw_do_sending(ubyte send_this)
{
    printf("doing HW sending 0x%02x\n",send_this);
    return 0;
}
F_CommandFunction my_hw_send_to_read = NULL;

int main (void)
{
    ubyte rx = 0x40;
    F_SetupLowerLayer(my_hw_do_init,my_hw_do_sending,&my_hw_send_to_read);

    my_hw_send_to_read(rx);
    getchar();
    return 0;
}
eaanon01
Care to elaborate, maybe explaining a practical use?
Leonardo Herrera
As an wxample if I have to write a test program using som HW interface that generates interupts in the end. Then this module can be setup to execute a function outside the normal scope as a signal/interrupt handler.
eaanon01
+1  A: 

Our codebase has a trick similar to

#ifdef DEBUG

#define my_malloc(amt) my_malloc_debug(amt, __FILE__, __LINE__)
void * my_malloc_debug(int amt, char* file, int line)
#else
void * my_malloc(int amt)
#endif
{
    //remember file and line no. for this malloc in debug mode
}

which allows for the tracking of memory leaks in debug mode. I always thought this was cool.

jdizzle
+1  A: 

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

fortran
A: 

I like the concept of container_of used for example in lists. Basically, you do not need to specify next and last fields for each structure which will be in the list. Instead, you append the list structure header to actual linked items.

Have a look on include/linux/list.h for real-life examples.

Viliam
A: 

Funny referencing to 1D arrays. I use it a lot - it makes my code clearer with more complex examples (for me!).

Example:

int tab[4] = {1,2,3,4};
int i;
for (i = 0; i < 3; i++)
    printf("%d", i[tab]);
dare2be
-1 This code is NOT clearer, and you should not write code for your own readability but for other programmers.
Tomas
Ok, the 'clarity' bit was not what I actually meant. I mean, at first when I saw this trick, I was like 'OMG! What is that?', but then got to like it and use it now and then. So right now I guess I am more used to the i[tab] notation than the conventional one. That's what I meant when I said "clearer".And yeah, you've certainly got the point about readability for other coders.
dare2be