What is your favorite C programming trick?

C

C Problem Overview


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 Solutions


Solution 1 - C

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.

Solution 2 - C

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

Solution 3 - C

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.

Solution 4 - C

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

Solution 5 - C

using __FILE__ and __LINE__ for debugging

#define WHERE fprintf(stderr,"[LOG]%s:%d\n",__FILE__,__LINE__);

Solution 6 - C

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};

Solution 7 - C

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

Something like:

#define return DoSomeStackCheckStuff, return

Solution 8 - C

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.

Solution 9 - C

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.

Solution 10 - C

Instead of

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

Use

#define print_dec(var)  printf("%s=%d\n",#var,var);
print_dec(counter);

Solution 11 - C

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;

Solution 12 - C

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

Solution 13 - C

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;
}

Solution 14 - C

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

Solution 15 - C

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]

Solution 16 - C

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.

Solution 17 - C

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

Solution 18 - C

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.

Solution 19 - C

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

Solution 20 - C

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.

Solution 21 - C

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.

Solution 22 - C

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

Solution 23 - C

See "Hidden features of C" question.

Solution 24 - C

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.

Solution 25 - C

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.

Solution 26 - C

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.

Solution 27 - C

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.

Solution 28 - C

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

Solution 29 - C

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;
}

Solution 30 - C

if(---------)  
printf("hello");  
else   
printf("hi");

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

Solution 31 - C

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

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

Solution 32 - C

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

Solution 33 - C

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");
}

Solution 34 - C

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

Solution 35 - C

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++ );

Solution 36 - C

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

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

it prints a+b.

Solution 37 - C

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

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

The answer is !printf("correct")

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsmcameronView Question on Stackoverflow
Solution 1 - CEvan TeranView Answer on Stackoverflow
Solution 2 - CfortranView Answer on Stackoverflow
Solution 3 - CJohn CarterView Answer on Stackoverflow
Solution 4 - CJacksonView Answer on Stackoverflow
Solution 5 - CPierreView Answer on Stackoverflow
Solution 6 - CJasper BekkersView Answer on Stackoverflow
Solution 7 - CAndrew BarrettView Answer on Stackoverflow
Solution 8 - CEvan TeranView Answer on Stackoverflow
Solution 9 - CBrian R. BondyView Answer on Stackoverflow
Solution 10 - CCostaView Answer on Stackoverflow
Solution 11 - CEvilTeachView Answer on Stackoverflow
Solution 12 - CSteve MelnikoffView Answer on Stackoverflow
Solution 13 - CNils PipenbrinckView Answer on Stackoverflow
Solution 14 - CJamieView Answer on Stackoverflow
Solution 15 - CGilad NaorView Answer on Stackoverflow
Solution 16 - CDan OlsonView Answer on Stackoverflow
Solution 17 - CgbarryView Answer on Stackoverflow
Solution 18 - ChamiltopView Answer on Stackoverflow
Solution 19 - CSimon WalkerView Answer on Stackoverflow
Solution 20 - CTim PostView Answer on Stackoverflow
Solution 21 - CYuval FView Answer on Stackoverflow
Solution 22 - CKarlView Answer on Stackoverflow
Solution 23 - CAlex BView Answer on Stackoverflow
Solution 24 - CViliamView Answer on Stackoverflow
Solution 25 - CepatelView Answer on Stackoverflow
Solution 26 - CJayGView Answer on Stackoverflow
Solution 27 - CjdizzleView Answer on Stackoverflow
Solution 28 - CsanjoydView Answer on Stackoverflow
Solution 29 - Ceaanon01View Answer on Stackoverflow
Solution 30 - CjustgoView Answer on Stackoverflow
Solution 31 - CMartin BeckettView Answer on Stackoverflow
Solution 32 - CJasonView Answer on Stackoverflow
Solution 33 - CsakraView Answer on Stackoverflow
Solution 34 - CAnton KView Answer on Stackoverflow
Solution 35 - CChrisView Answer on Stackoverflow
Solution 36 - CramshankarView Answer on Stackoverflow
Solution 37 - CramshankarView Answer on Stackoverflow