PhD Student at the University of Victoria

C Tricks

C is a relativity old and simple language compared to most of the other heavily used languages. Over time lots of little tricks have developed to solve certain problems that arise when programming in such a simple language.

do while 0

If you spend enough time looking through C code, you might find this (at first odd looking) idiom. It will look something like this:

		do {
	
			/* some code */
	
		} while (0)
	

At first you might think this doesn't do anything, but it does in fact have a purpose. The idea is that although the block is only executed once, and the do block is a single statement. That means that the code inside will not be affected by the code around it. This is particularly useful when it is in a macro.

		#define FOO(x)  \\ 
	
		do {  \\
	
			/* some code that won't be mucked up when foo inserts it somewhere */ \\
	
		} while (0) \\
	

The reason for this is that FOO could be used in a place that expects a sinlge statement. Maybe something like this:

	if(a)
	
	    FOO(x);
	

But if FOO inserts more than one statement, only the first would be in the if statment. Which still may compile, but might lead to some unforseen effects.

I'm sure this is mentioned in lots of places. I first discovered it in the kernel newbies guide to kernel coding.


 

minclude

This stands for machine specific include. This is a way to include architecture specific files without help from the build system. The idea is that you recreate the include path with an extra level of directory for the architecture. In GCC when you compile one of the default preprocessor flags is the machines architecture. the mincude just does a regular include of the file, with the arch flag stuck in front (or back). This causes a different path to be generated based on the arch flag.


 

#if 0

This is something I hope to not see too many more times in my life. It does exactly what it looks like -- removes everything up to the next #endif. The idea used to be that you could remove large blocks of code comments and all. The problem is the poor fool who comes in later and is reading further down in the file than this and then wonders why his code doesn't doesn't see this code.

If you want to remove some code, uses an editor modern enough to insert a "//" on each line of the removed code, and save the next person (maybe me?) the headache.


 

inline

There is no longer any if or buts about this: there is no place in modern programming for inline. Your time is better spent learning your compilers optimization options. In gcc, inline doesn't even inline things. It is just used as a hint (and not a very strong one) to the compiler. I don't think gcc even inlines anything unless you are using -O2 or above. There is an __always_inline__ attribute you can use instead. If you need to optimize your code, buy a book on how to optimize, don't bother sticking the inline attribute on things.

So why not inline everything? Well it makes your code bigger. You might think that is okay, but its not. Bigger code doesn't fit in caches as well. And cache locality is far more important than instructions executed. When you inline, you save the cost of constructing a stack frame, but this cost is minor (100s of times smaller?) compared to the cost of fetching something from memory (that couldnt fit in the cache because it had your inlined code in it).

 

So whats the compiler doing that's so smart? Well first off it knows who's calling what and how often (at least with profile data). It also knows how big your code is with and without the inlining. The compiler takes your whole program into consideration, and the machine it runs on, then tries to come up with the optimal set of functions to inline. That is probably better than what you can do, so just learn how to use the compiler, and let it do its job.