C Preprocessors

From Wikiversity
Jump to: navigation, search

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[edit]

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:

typedef tagMYSTRUCT {
    int a, b, c;
} MyStruct_t;

And this code in Program.c:


#include "Header.h"
main ()
{

}

Program.c will be compiled as:

typedef tagMYSTRUCT {
    int a, b, c;
} MyStruct_t;
main ()
{

}

#define[edit]

Constants

Syntax: #define <keyword> <value>

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:

#define MAX_COUNT    10
#define FILENAME     "Data.dat"

Macros

Syntax: #define <keyword>(<param1>,<param2>,...<paramn>) <Actual Syntax>

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:

#define SUM(a,b,c) (a)+(b)+(c)
#define MAX(a,b)   ((a)>(b))?(a):(b)

#if - #else - #endif[edit]

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:

#define MAX_VALUE 10

#if (MAX_VALUE == 10)
printf("Correct max value");
#else
printf("Incorrect max value");
#endif

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

#ifdef / #ifndef[edit]

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:

#define MAX_VALUE 10

#ifdef MAX_VALUE
printf("Max value is defined");
#endif

#ifndef MAX_VALUE
printf("Max value is not defined");
#endif

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

#pragma[edit]

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:

#pragma pack      // Sets the packing alignment for elements of struct and union definitions
#pragma once      // Ensures that a header file is included only once (in case of recursive includes)


See also[edit]