As can be seen from The C compilation model, before the compiler is called, the C program is passed through a preprocessor. The basic job of the C preprocessor is to replace every occurrence of what we call a macro with the string that it represents. Below are the different functionality provided by the C preprocessor.
#include
The #include preprocessor directive tells the preprocessor to include whatever file is named after it into the current file. There are two methods to use #include as #include “filename” or #include <filename>. The difference is that in the former case, the preprocessor will search for the file in the current directory and if it is not present will search in the standard directory(whose path is set in the system eg: /usr/local/include) and in the latter case, it will search only in the standard directory.
The header file is a good concept to separate the variable and function declarations which need to be used by another file or many files as seen above. This can be seen in Modular structure of a C program.
One question that I have wondered about is that is it possible to include any file using #include? Generally, we just include header files in a C program as seen above. What happens if I use something like #include “foo.c”?
The answer is yes we can include a C file into another C file. But it is also suggested not to do so. One reason is that generally when development environments compile a project, they compile all the C files and create .obj files. So you might end up with two obj files containing the same symbols and will get a linker error.
#define
The #define macro is used to define a replacement text. So when the preprocessor will parse the C file, it will replace all instances of the macro with the definition that it represents. The usage is:
#define name replacement_text
#define MAX 1000
int main()
{
int a = 20;
int b = a + MAX; /* after the preprocessing this statement changes to "int b = a + 1000"; */
printf("b = %dn", b); /* This prints b = 1020 */
return 0;
}
#define can also be used along with arguments. A typical example will make this clear.
#define MAX(a, b) (a > b) ? a : b
int main()
{
int a = 100;
int b = 200;
printf("Max = %dn", MAX(a, b)); /* prints Max = 200 */
return 0;
}
Care has to be taken when using such arguments because the #define macro leads to the expansion of the definition. So,
#define square(x) x*x used as square(z+1) expands to z+1*z+1 which is wrong. We should use parenthesis instead as #define square(x) ((x)*(x))
The “#” symbol is used to replace the argument with the name of the argument.
#define print(x) printf("#x = %dn", x)
print(varText) will expand to printf("varText = %dn", varText);
This function is great for printing in any logging functionality.
The ‘##’ preprocessor symbol can be used to concatenate two arguments placed next to each other in the macro.
#define combine(name, number) name ## number combine(table, 1) /* this will expand to "table1" */
#if, #ifdef
#if enables us to use conditional checking in a preprocessor.
#if (SYSTEM == WINDOWS) #include"windows.h" #elif (SYSTEM == UNIX) #include "unix.h" #else #include "linux.h" #endif
There is a special way to check if a header file is already included. Suppose we have a header sys_header.h.
system.h
#include "sys_header.h"
main.c
#include "system.h" #include "sys_header.h"
This will cause the problem of duplicate definitions because sys_header.h gets included two times, one already in system.h and another one explicitly. This can be avoided by placing the following in sys_header.h. Infact, this is a good programming practice to follow in any header file.
#ifndef SYS_HEADER_H #define SYS_HEADER_H ... #endif /* SYS_HEADER_H */
What this does is that when we include sys_header.h, it will first check if SYS_HEADER_H macro is defined or not. If we have already included sys_header.h, then the SYS_HEADER_H will be defined and so it will not be included again.
#error
The #error macro is used by the preprocess to indicate an error condition and to print out that error on the screen.
#define BUFFER_SIZE 255 #if BUFFER_SIZE < 256 #error "BUFFER_SIZE is too small." #endif
This will cause the compilation to stop and print the message on the screen.
Related Posts:
Tags: C, preprocessor


Hi Kevin,
Nice to know more things on C in this blog.
One thing…#define square(x) (x*x) should be #define square(x) ((x)*(x)) ..otherwise it is same as #define square(x) x*x
[Reply]
Good to see that you are reading my blog
Yes, that is correct it should be ((x)*(x)).
[Reply]
Seems like you have more or less a FULL C teaching materials up here…
[Reply]
Kevin Reply:
December 25th, 2009 at 2:36 am
Yes. But I would like it to contain material from experiences so that it helps people who read them.
[Reply]