Skip to content
Home » All Posts » A Closer Look at the C Preprocessor

A Closer Look at the C Preprocessor

c preprocessor

Introduction

C preprocessor is a tool that runs before the actual compilation process and performs various tasks such as file inclusion, macro expansion, conditional compilation, and more. It is automatically invoked by the compiler so you often do not have to manually invoke it.

The most common C preprocessors are:

  • #include
  • #define
  • #ifdef, #ifndef, #else, #endif

The #Include C Preprocessor Clause

#include preprocessor clause is the most commonly used clause to (as you have guessed) include other header or source files to gain access to their functions or variables. Please note that including headers from standard C library needs to enclose the header file name with < > while including user-defined headers needs to enclose the header file with " " .

/* These include C standard libraries so we have access to printf() below */
#include <stdio.h>
#include "myfuncs.h"

int main(void)
{
	/* we can call printf() function because we have included <stdio.h> from the standard C library */
	printf("this line is not compiled");

	/* we can use promptAndPrint() function because we have included "myfuncs.h" from user-defined implementation */
	printHelloWorld();
	return 0;
}

The #Define C Preprocessor Clause

Also a very popular clause, it is used to define Macros that tells the compiler to replace certain keyword with other contents before compiling the code. A Macro is not a variable; it does not occupy memory space like a variable does. A Macro normally defines a static value that does not change or abstracts a complex instructions into one line.

Defining a Macro normally does not require a semicolon, but a semicolon may be required when we define a multi-line Macro. In addition, we have to use back-slash (\) at the end of each line of a Macro in a multi-line Macro. See example below.

#include <stdio.h>

/* define static values that normally do not change */
#define NUM_MONTH_IN_A_YEAR 12
#define NUM_DAY_IN_A_YEAR 365

/* define a function-like macro that computes the square value */
#define SQUARE(x) ((x) * (x))

/* define a multi-line macro that computes the sum of 2 square values */
#define SUM_OF_SQUARES(x, y) \
    do { \
        int square_x = (x) * (x); \
        int square_y = (y) * (y); \
        (square_x + square_y); \
    } while (0)

int main(void)
{
	printf("there are %d month or %d days in a year", NUM_MONTH_IN_A_YEAR, NUM_DAY_IN_A_YEAR);

	printf("%d squared is %d", 5, SQUARE(5));

	printf("The sum of squares for %d and %d is %d\n", 5, 10, SUM_OF_SQUARES(5, 10));

	return 0;
}

Conditional Compilation

It is also quite common to use conditional compilation preprocessor clauses (#ifdef, ifndef, #else, #endif) to control what is compiled or not compiled based on some condition. The condition can be set using the #define clause but without value.

In the example below, line 9 and 15 are compiled while 11 and 17 are not compiled.

#include <stdio.h>

// Define a preprocessor macro
#define DEBUG

int main(void) 
{
#ifdef DEBUG
	 printf("Debugging enabled\n");
#else
	 printf("Debugging disabled\n");
#endif

#ifndef RELEASE
	 printf("Not in release mode\n");
#else
	 printf("in release mode\n");
#endif
	 return 0;
}

Related Pages

Join the conversation

Your email address will not be published. Required fields are marked *