Summary: in this tutorial, you will learn about C preprocessor to create a macro, control the compilation of C program and include header files.
Introduction to C preprocessor
In C compilation model and processes, the C source code is passed to a preprocessor before being transferred to the compiler. The preprocessor interprets all preprocessor directives or macros by substituting the macros by their contents.
The preprocessor has its own syntax which is different from the C syntax. All the preprocessor begins with a hash ( #
) sign e.g., #define
, #include
C preprocessor has many usages including defining a macro, control the compilation conditionally and including header files.
The #define statement
The #define
statement was the only way to define a constant in C before the const
keyword was introduced. The following example uses the #define
statement to define a constant:
#define MAX 100
Code language: C++ (cpp)
The general syntax of the define statement is as follows:
#define name substitute-text
Code language: C++ (cpp)
Where name can be any valid C identifier and substitute-text
can be anything, not limited to a constant. For example, you can use the #define
statement to create new macros as follows:
#include <stdio.h>
#define begin {
#define end }
int main()
{
int i = 0;
if(i == 0)
begin
printf("Hello world!\n");
end
return 0;
}
Code language: C++ (cpp)
However, creating the macros like these is considered bad programming practice because they change the C language constructs and make the code more difficult to maintain.
Conditional compilation
Sometimes you may want to put your own code into the program to debug it in the development environment and remove it in the production environment so that you can troubleshoot the problems faster. You can achieve this with #ifdef
and # endif
directives, for example:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 9
void sort(int* a, const int size);
int main()
{
int a[SIZE] = {1,3,2,6,4,5,8,7,9};
sort(a,SIZE);
return 0;
}
void sort(int* a, const int size)
{
int i,j, k;
#if DEBUG
printf("Before sorting:\n");
for(i = 0; i < size; i++)
{
printf("%d ",a[i]);
}
#endif // DEBUG
for (i = 1; i < size; ++i)
{
k = a[i];
j = i - 1;
while ((j >= 0) && (k < a[j]))
{
a[j + 1] = a[j];
--j;
}
a[j + 1] = k;
}
#if DEBUG
printf("\nAfter sorting:\n");
for(i = 0; i < size; i++)
{
printf("%d ",a[i]);
}
#endif // DEBUG
}
Code language: C++ (cpp)
The compiler will check if DEBUG
is defined, it will include the code between the #if
and #endif
section. You can switch the debugging mode ON or OFF by using command line when you compile the code, for example:
% cc -DDEBUG -g -o prog main.c
Include header files
C preprocessor allows a program to include source code from another file by using the #include
directive e.g., we often use #include
directive to include file from standard library function such as stdio.h
:
#include <stdio.h>
Code language: C++ (cpp)
The angle bracket <>
indicates that the file is the standard header file.
If you want to include your own header file e.g., stack.h
in your program, you use the double quotes ( ""
) instead of the angle bracket ( <>
):
#include "stack.h"
Code language: C++ (cpp)
File including can be nested and sometimes it causes the problem. For example, you define a structure that describes a node of a linked list in the util.h
file:
struct node
{
int data;
struct node* next;
} head;
Code language: C++ (cpp)
And you include the util.h
file in both stack.h
and queue.h
files. The, in the main program, you include both stack.h
and queue.h
files as follows:
include "stack.h"
include "queue.h"
Code language: C++ (cpp)
It causes a fatal error saying that the node
structure is redefined because the util.h
was included twice in both stack.h
and queue.h
files.
A good way to avoid this issue is using the #ifndef
directive as follows:
#ifndef UTIL_H_INCLUDED
#define UTIL_H_INCLUDED
struct node
{
int data;
struct node* next;
} head;
#endif // UTIL_H_INCLUDED
Code language: C++ (cpp)
If the UTIL_H_INCLUDED
is not defined, it will define UTIL_H_INCLUDED
and the node
structure, otherwise, no code in the util.h
is included. By doing this, the util.h
header file is included only one.
In this tutorial, we have shown you how to use C preprocessor to create a macro, control the compilation conditionally and include header files in the program.