C Programming/Preprocessors

Introduction
Preprocessors are constructs in C that instruct the compiler to make modifications to the code according to certain conditions before compilation. Some preprocessors also force the compiler to behave in a certain way.

Although most preprocessors have non-preprocessor equivalents, preprocessors are preferred over some C constructs because they are more efficient and create more optimized binaries.

#include
Previously mentioned in the introductory chapter, #include is used to insert the contents of a source file into another source file. This is generally used for header files containing constant definitions, type definitions, and function prototypes that will be used in your source code.

Example: Given this code in Header.h:

And this code in Program.c:

Program.c will be compiled as:

#define
Constants

Syntax: #define

Generally used to define constant values and similar in use to the const keyword in C syntax. The difference is how the code is compiled. A const variable will still use memory space. All constants defined using #define, however, will be replaced in the source code before compilation.

The preprocessor #define is not type-sensitive and will accept any data type as a value. Just remember that the value you set using the #define preprocessor will be replaced in your code wherever the keyword is used.

Example:

Macros

Syntax: #define (, ,... ) 

The #define preprocessor is also used to define "macros", or lightweight functions. These functions do not have assembly code of their own and are not invoked during run time. Instead, they are embedded into the code during compile time. This is similar to the inline keyword for functions.

Macros are used as an alternative to creating separate functions for short operations.

Example:

#if - #else - #endif
Similar in use to the "if" construct in C. However, #if statements are processed before compilation. This means that #if determines which parts of the code will be compiled. Oftentimes, #if is used in conjunction with #define statements. You can use #if to check the value of a defined constant and determine whether a certain part of the code will be compiled.

Like the "if" construct, #if accepts an integer value. Zero is considered false; any non-zero value is considered true. Standard C comparison operators can be used.

Example:

In this case, since MAX_VALUE is defined as 10, then only the first printf statement will be compiled.

#ifdef / #ifndef
This is a logical extension of #if. #ifdef will check if a specified macro/constant has been defined (#ifndef or "if not def" is the logical opposite of #ifdef). To end a #ifdef/#ifndef block, #endif is also used.

Example:

In this case, the first printf statement is compiled because MAX_VALUE has been defined previously.

#pragma
This is a seldom used preprocessor. This preprocessor is compiler-dependent (i.e. Visual Studio and gcc have a different set of pragma operators). #pragma is used together with another operator/keyword to force the compiler to behave in a certain way.

Example:

Additional Resources

 * C preprocessor @ Wikipedia

Assignments

 * Previous Lesson: Memory Management
 * Course Home Page