C Preprocessor

Summary: in this tutorial, you will learn about C preprocessor to create a macro, control the compilation of C program and include header files.

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

Was this tutorial helpful ?