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?

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
smcameron
  • 758
  • 4
  • 7
  • 8

37 Answers37

80

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.

Michael Myers
  • 188,989
  • 46
  • 291
  • 292
Evan Teran
  • 87,561
  • 32
  • 179
  • 238
  • 2
    I believe your first example can also be written as `&(int){1}`, if you want to make it slightly more clear what your intent here is. – Lily Ballard Oct 14 '11 at 21:37
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

fortran
  • 74,053
  • 25
  • 135
  • 175
  • 13
    You can't say carmack in an optimization thread without mentioning the fast inverse sqrt that was in the quake source. http://en.wikipedia.org/wiki/Fast_inverse_square_root – pg1989 Oct 14 '11 at 14:56
  • Where did he get 0x5f3759df from in the first place? – Rory Harvey Oct 14 '11 at 16:23
  • 2
    @RoryHarvey: From what I could find when looking it up, it seems it was purely empirical. Some studies (I don't remember where I saw them) demonstrated that it was close to optimal, but not fully optimal. Likewise, it seems that for 64bits the value was discovered, rather than computing. – Matthieu M. Oct 14 '11 at 16:28
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.

Community
  • 1
  • 1
John Carter
  • 53,924
  • 26
  • 111
  • 144
  • Not needed for global variables, by the way. – strager Mar 01 '09 at 20:41
  • 5
    Not needed for _static_ variables. Global variables may be zeroed, but it's not a requirement. – Jamie Oct 23 '09 at 13:23
  • 4
    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 Nov 02 '09 at 15:55
45

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...

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Jackson
  • 5,627
  • 2
  • 29
  • 48
  • 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 Mar 01 '09 at 07:31
  • 4
    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 Mar 01 '09 at 08:12
  • Last time I mentioned Duff's Device I got serious downvoted! :) – Mitch Wheat Mar 01 '09 at 09:31
  • ^^ 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 Mar 01 '09 at 09:52
  • While it may be a micro-optimisation, in the context of *this* question it seems a perfect answer. – Richard Mar 01 '09 at 12:04
  • 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 Mar 02 '09 at 09:37
  • 6
    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 Mar 03 '09 at 18:09
  • 1
    +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 Jun 30 '09 at 09:24
  • 3
    The anger will be from your colleagues and successors who have to maintain your code after you. – Jonathan Leffler Nov 02 '09 at 15:50
  • 1
    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 Nov 02 '09 at 16:58
  • I'm not voting because I downvote for Duff's Device being evil, but it up-vote for "Not having a chance to use it in anger" yes, Duff's Device is a weapon. – Brian Postow Feb 11 '11 at 16:01
  • 1
    Duff's Device may be a micro-optimization, but it is so well known by now that I wouldn't consider it unreadable - if you haven't seen it, you have no business writing C. – evil otto Oct 14 '11 at 19:23
42

using __FILE__ and __LINE__ for debugging

#define WHERE fprintf(stderr,"[LOG]%s:%d\n",__FILE__,__LINE__);
Pierre
  • 34,472
  • 31
  • 113
  • 192
  • 6
    On some compilers you get __FUNCTION__ as well. – JBRWilkinson Nov 02 '09 at 16:11
  • 11
    `__FUNCTION__`is just an alias for `__func__`, and `__func__` is in c99. Quite handy. `__PRETTY_FUNCTION__` in C (GCC) is just another alias for `__func__`, but in C++ it will get you the full function signature. – sklnd Oct 14 '11 at 15:24
  • __FILE__ shows full path of filename so i use basename(__FILE__) – Jeegar Patel Jan 24 '12 at 16:50
31

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,711
  • 32
  • 46
28

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

Something like:

#define return DoSomeStackCheckStuff, return
RJFalconer
  • 10,890
  • 5
  • 51
  • 66
Andrew Barrett
  • 19,721
  • 4
  • 47
  • 52
  • 4
    Hopefully that was #define'd in the function body and #undefine'd at the end! – strager Mar 01 '09 at 20:40
  • Not very fond of that - first thing that comes to my mind is that DoSomeStackCheckStuff screws up memory because of some bug and whoever is reading the code is not aware of the redefinition of return and is wonders what the /hell/ is going on. – gilligan Oct 14 '11 at 15:33
  • 8
    @strager But that would make it basically useless. The whole point is to add some tracing to *every* function call. Otherwise you would just add a call to `DoSomeStackCheckStuff` to the functions you wanted to trace. – Clueless Oct 14 '11 at 15:33
  • 1
    @gilligan I don't think this is the type of thing you leave enabled all the time; it seems pretty handy for one-shot debugging work. – sunetos Oct 14 '11 at 17:01
  • does that really work? :) I would have written `#define return if((DoSomeStackCheckStuff) && 0) ; else return`... just as crazy I guess! – Paolo Bonzini Oct 14 '11 at 19:14
  • @Clueless, One function (or set of functions) can have multiple instances of `return`. – strager Oct 14 '11 at 19:25
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.

Evan Teran
  • 87,561
  • 32
  • 179
  • 238
  • 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 Mar 01 '09 at 07:36
  • 4
    "... 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 Mar 01 '09 at 08:27
  • 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 Mar 01 '09 at 10:28
  • I use this too, and it's beautiful. +1. – strager Mar 01 '09 at 20:41
  • 3
    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 Nov 02 '09 at 16:11
  • 3
    @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 Jul 08 '10 at 20:42
  • But what about padding *after* str? That's what it takes care of. – rpjohnst Oct 14 '11 at 14:08
  • 2
    @Rusky: How would that negatively effect anything? Suppose there is "padding" after `str`. OK, When I allocate `sizeof(struct X) + 10` Then this makes `str` effectively `10 - sizeof(int)` (or more, since we said there is padding) big. This **overlays** `str` and any padding after it. The only way that it would have **any** difference, is if there were a member after `str` which breaks the whole thing anyway, flexible members must be the last. Any padding at the end will only possibly cause too much to be allocated. Please provide a specific example of how it could actually go wrong. – Evan Teran Oct 14 '11 at 15:07
  • @Rusky: Allocating too much, in the quantities we are talking about (1-8 bytes or so) would not negativly effect the program in any way. You do realize that **any** time you `malloc`, there is a good chance that the allocator will allocate give you a block of memory bigger than asked (often by amounts in the range of 1-8 bytes...). To be honest, odds are that padding or not, due to allocator alignment needs, you'll get the same size block. – Evan Teran Oct 19 '11 at 14:08
17

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
  • 339,232
  • 124
  • 596
  • 636
  • 2
    Is there still something out there that translates C++ into C, like cfront used to? – MarkJ Mar 01 '09 at 15:13
  • 11
    This is hardly object orientation. For OO with inheritance, you'll need to add some kind of virtual function table to your object struct, which can be overloaded by "subclasses". There are lots of half-baked "C with classes" -style frameworks out there for this purpose but I recommend staying out of it. – exDM69 Oct 14 '11 at 13:10
  • It needed to be said. +1 for that. – Amit S Oct 14 '11 at 14:24
  • 3
    @exDM69, object orientation is as much a way of thinking about a problem as it is a coding paradigm; you can do it successfully without inheritance. I did this on a few projects before jumping full bore into C++. – Mark Ransom Oct 14 '11 at 14:43
16

Instead of

printf("counter=%d\n",counter);

Use

#define print_dec(var)  printf("%s=%d\n",#var,var);
print_dec(counter);
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Costa
  • 461
  • 7
  • 13
14

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
  • 28,120
  • 21
  • 85
  • 141
11

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
  • 2,620
  • 1
  • 22
  • 24
  • This feels dangerous. These are declaration and definition that do not match. While compiling `Source2.c`, the compiler might assume that `MyVar` does not change, even across a function call to `Source1.c`. (Note that this, as an actual const variable, differs from a pointer to const. In the latter case, the pointed-to object might still be modified via a different pointer.) – jilles Oct 16 '11 at 16:44
  • 1
    This does not produce variable that is readonly only in some compilation units. This produces undefined behavior (see p. 6.2.7.2 of ISO 9899 and also p. 6.7.3.5). – Ales Hakl Oct 16 '11 at 17:43
8

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;
}
strager
  • 88,763
  • 26
  • 134
  • 176
Nils Pipenbrinck
  • 83,631
  • 31
  • 151
  • 221
  • ... and gcc actually inlines it :) +1 – Tim Post Mar 01 '09 at 18:32
  • 2
    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 Mar 01 '09 at 20:42
  • 3
    "a good deal faster than using a branch": the difference being that the branch is correct for all values of `v`, whereas the `halfshift` trick only doubles the allowable range to 63 on a 32-bit architecture, and 127 on a 64-bit one. – Pascal Cuoq Oct 14 '11 at 13:18
8

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
  • 7,075
  • 12
  • 56
  • 86
  • One technique I like with this is, if you have a function that requires initialization, you initialize the pointer with a call to the initialization routine. When that runs, the last thing it does is replace the pointer with a pointer to the actual function, then call that function. That way, the initializer automatically gets called the first time the function is called, and the real function gets called every subsequent time. – TMN Oct 14 '11 at 20:49
7

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]
EvilTeach
  • 28,120
  • 21
  • 85
  • 141
Gilad Naor
  • 20,752
  • 14
  • 46
  • 53
  • 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 Mar 01 '09 at 06:58
  • 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 Mar 01 '09 at 07:03
  • I hate the C preprocessor ... :( – hasen Mar 01 '09 at 07:11
  • 1
    Yes, I tried it. I cut and pasted the error message from the compiler, which was gcc. – smcameron Mar 01 '09 at 07:11
  • 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 Mar 01 '09 at 07:14
  • COMPILE_ASSERT(1); COMPILE_ASSERT(1); int main(int argc, char *argv[]) { printf("hello world\n")' } (see if that fits.) – smcameron Mar 01 '09 at 07:18
  • 1
    @Gilad: it is legal in c++ to have redundant typedefs, but not in c. – Evan Teran Mar 01 '09 at 07:18
  • Okay, I stand corrected. Another thing learned today. – Gilad Naor Mar 01 '09 at 07:28
6

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
  • 22,849
  • 4
  • 42
  • 56
  • I have actually used this technique in practice to make the code driving a sequence of dependent asynchronous I/O vaguely human-readable. The main difference is that I don't store the coroutine state in a `static` variable but instead allocate a struct dynamically and pass a pointer to that into the coroutine function. A bunch of macros make this more palatable. It's not nice but better than the async/callback version that jumps all over the place. I'd use green threads (via `swapcontext()` on *nixes) if I could though. – pmdj Oct 14 '11 at 19:07
6
#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
  • 10,352
  • 6
  • 33
  • 43
6

I'm a fan of xor hacks:

Swap 2 pointers without third temp pointer:

int * a;
int * b;
a ^= b;
b ^= a;
a ^= b;

Or I really like the xor linked list with only one pointer. (http://en.wikipedia.org/wiki/XOR_linked_list)

Each node in the linked list is the Xor of the previous node and the next node. To traverse forward, the address of the nodes are found in the following manner :

LLNode * first = head;
LLNode * second = first.linked_nodes;
LLNode * third = second.linked_nodes ^ first;
LLNode * fourth = third.linked_nodes ^ second;

etc.

or to traverse backwards:

LLNode * last = tail;
LLNode * second_to_last = last.linked_nodes;
LLNode * third_to_last = second_to_last.linked_nodes ^ last;
LLNode * fourth_to_last = third_to_last.linked_nodes ^ second_to_last;

etc.

While not terribly useful (you can't start traversing from an arbitrary node) I find it to be very cool.

hamiltop
  • 453
  • 6
  • 9
5

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

In the header declare

#ifndef RELEASE
#  define D(x) do { x; } while (0)
#else
#  define D(x)
#endif

In your code place testing statements eg:

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

The do/while helps in case the contents of the macro expand to multiple statements.

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

Community
  • 1
  • 1
Simon Walker
  • 5,523
  • 6
  • 30
  • 32
  • 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 Mar 01 '09 at 14:53
  • 3
    @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 Mar 01 '09 at 20:50
  • 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 Mar 02 '09 at 13:35
  • 1
    @AdamRosenfield: Using `#define D(x) do { } while(0)` instead handles that case (and can be applied to the branch that inserts `x` as well for consistency) – rpetrich Oct 14 '11 at 14:40
3

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.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Tim Post
  • 33,371
  • 15
  • 110
  • 174
  • 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 Mar 01 '09 at 06:42
  • 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 Mar 01 '09 at 07:03
  • 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 Mar 01 '09 at 07:06
3

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.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Yuval F
  • 20,565
  • 5
  • 44
  • 69
3

Not specific to C, but I've always liked the XOR operator. One cool thing it can do is "swap without a temp value":

int a = 1;
int b = 2;

printf("a = %d, b = %d\n", a, b);

a ^= b;
b ^= a;
a ^= b;

printf("a = %d, b = %d\n", a, b);

Result:

a = 1, b = 2

a = 2, b = 1

Community
  • 1
  • 1
Karl
  • 14,434
  • 9
  • 44
  • 61
2

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
  • 4,404
  • 3
  • 28
  • 30
2

See "Hidden features of C" question.

Community
  • 1
  • 1
Alex B
  • 82,554
  • 44
  • 203
  • 280
1

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.

e.James
  • 116,942
  • 41
  • 177
  • 214
epatel
  • 45,805
  • 17
  • 110
  • 144
  • 1
    I wish that I understood what you meant here. Could you explain more? What is a userdata pointer? – Zan Lynx Mar 02 '09 at 14:49
  • 1
    Plz see here http://stackoverflow.com/questions/602826/what-is-a-good-definition-of-a-userdata-pointer – epatel Mar 03 '09 at 10:29
  • 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 Mar 03 '09 at 18:31
  • Ah, yes. Thanks. I use this a lot, but I have never called it that. – Zan Lynx Mar 03 '09 at 22:39
1

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.

Community
  • 1
  • 1
JayG
  • 4,339
  • 3
  • 23
  • 19
1

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
  • 4,078
  • 1
  • 30
  • 38
1

Fun with macros:

#define SOME_ENUMS(F) \
    F(ZERO, zero) \
    F(ONE, one) \
    F(TWO, two)

/* Now define the constant values.  See how succinct this is. */

enum Constants {
#define DEFINE_ENUM(A, B) A,
    SOME_ENUMS(DEFINE_ENUMS)
#undef DEFINE_ENUM
};

/* Now a function to return the name of an enum: */

const char *ToString(int c) {
    switch (c) {
    default: return NULL; /* Or whatever. */
#define CASE_MACRO(A, B) case A: return #b;
     SOME_ENUMS(CASE_MACRO)
#undef CASE_MACRO
     }
}
sanjoyd
  • 3,260
  • 2
  • 16
  • 22
0
if(---------)  
printf("hello");  
else   
printf("hi");

Fill in the blanks so that neither hello nor hi would appear in output.
ans: fclose(stdout)

Álvaro González
  • 142,137
  • 41
  • 261
  • 360
justgo
  • 41
  • 3
  • you can format code with the `{}` toolbar button (I've done it for you). The "Quote" button doesn't keep whitespace or apply syntax highlighting. – Álvaro González Feb 11 '11 at 11:49
0

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
  • 1,069
  • 7
  • 9
  • 4
    Care to elaborate, maybe explaining a practical use? – Leonardo Herrera Nov 02 '09 at 16:17
  • 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 Nov 03 '09 at 07:14
0

Using the otherwise pointless ? : operator to initialise a const variable

const int bytesPerPixel = isAlpha() ? 4 : 3;

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
0

I always liked dumb preprocessor tricks to make generic container types:

/* list.h */
#ifndef CONTAINER_TYPE
#define CONTAINER_TYPE VALUE_TYPE ## List
#endif
typedef struct CONTAINER_TYPE {
    CONTAINER_TYPE *next;
    VALUE_TYPE v;
} CONTAINER_TYPE;
/* Possibly Lots of functions for manipulating Lists
*/
#undef VALUE_TYPE
#undef CONTAINER_TYPE

Then you can do e.g.:

#define VALUE_TYPE int
#include "list.h"
typedef struct myFancyStructure *myFancyStructureP;
#define VALUE_TYPE myFancyStructureP
#define CONTAINER_TYPE mfs
#include "list.h"

And never write a linked list again. If VALUE_TYPE is always going to be a pointer, then this is an overkill, since a void * would work just as well. But there are often very small structures for which the overhead of indirection often doesn't make sense. Also, you gain type checking (i.e. you might not want to concatenate a linked list of strings with a linked list of doubles, even though both would work in a void * linked list).

Jason
  • 1,059
  • 9
  • 13
  • I think it would be cleaner to have a function like macro, maybe `DECLARE_LIST`, which takes the type of the value as a parameter. – sanjoyd Oct 14 '11 at 19:34
0

In C99 you can directly embed URLs into source code inside functions. Example:

#include <stdio.h>

int main(int argc, char** argv) {
    http://stackoverflow.com/
    printf("Hello World");
}
sakra
  • 62,199
  • 16
  • 168
  • 151
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
Anton K
  • 4,658
  • 2
  • 47
  • 60
-1

Adding two numbers (a and b) without using any operators:

printf("%d", printf("%*s%*s",a,"\r",b,"\r") );

it prints a+b.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
-1

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++ );
Ed S.
  • 122,712
  • 22
  • 185
  • 265
Chris
  • 6,702
  • 8
  • 44
  • 60
-4

fill in the blanks to print both 'correct' and 'wrong' below:

if(--------)
printf("correct");
else
printf("wrong");

The answer is !printf("correct")