Advanced C Preprocessor Tricks
Many people are familiar with the classic #ifdef and #define preprocessor commands in C. However, there are many more that are actually surprisingly useful:
Stringification.
This is useful for extracting variable names, enum names, and compound expressions (think how assert is able to print the expression). This is done with the # prefix as follows:
output: "hello"
Cause compilation to stop upon reaching a line of code.
This is useful when you have incompatible #define
statements, such as using DirectX on a Linux build. This is logically performed with the #error
statement.
Cause compilation to report a warning upon reaching a line of code.
This is very similar to #error
, and is instead logically labeled #warning
.
Replace header define guards.
I don’t know why this isn’t more common, every modern C compiler seems to support the statement #pragma once
, which tells the compiler only to include the file once.
Produce a custom bookmark in your code.
The #pragma mark
command will produce a bookmark in your code that you can jump to. For instance, you could have the code:
This should create two bookmarks in your text editor (often seen with the class/function hierarchy viewer), one for public functions, and another for private functions.
Variable number of macro parameters.
Starting in C99, the preprocessor supports variadic macro parameters. This means you can use variable number of macro parameters like with varargs. Functions with an ellipsis are expanded to __VA_ARGS__
. Wikipedia provides a nice example duplicated for convenience and posterity:
Define structure packing.
There are several structure packing pragmas that describe alignment to the compiler. This can also be done with __attribute__
. More information here and here.
Token concatenation.
This one is pretty nifty. Say you have a function call that depends upon the name of the variable. You can use token concatenation to generate a token that specifies the function of interest:
File name and line number.
The macros __FILE__
and __LINE__
produce file name (as char*) and line number (as int), respectively.
Some of this information and more can be found in the GCC online documentation for macros: http://gcc.gnu.org/onlinedocs/cpp/Macros.html, pragmas http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html, and Microsoft’s MSVC preprocessor documentation http://msdn.microsoft.com/en-us/library/y4skk93w%28v=VS.80%29.aspx. Be careful of compiler specific preprocessor tricks like push_macro, the ones listed here seem to work fine with both GCC and MSVC.
If you are only using GCC, there is a nice overview of some neat GCC C Extensions here: http://popcnt.org/2008/03/useful-c-extensions-gcc-specific.html