C++ Preprocessor Directives

In this C++ programming tutorial we will look at compiling and preprocessor directives. Whenever a CPP program is compiled then the following steps are taken:

preprocessor, compiler and linker stages

The pre-processor is a utility program, which processes special instructions that can be or are written in a C/CPP program. These instructions can be include a library or some special instructions to the compiler about some certain terms used in the program.

Pre-processor directives start with ‘#’ character.

Different preprocessor directives (commands) perform different tasks. We can categorize the Preprocessor Directives as follows:

  • Inclusion Directives
  • Macro Definition Directives
  • Conditional Compilation Directives
  • Other Directives

Inclusion Directive

This category has only one directive, which is called #include. This inclusion directive is used to include files into the current file. The inclusion directive can be used as follows:

#include <stdio.h> includes stdio.h from include
folder
#include <iostream> includes cpp class library header
iostream
#include<my.cpp> includes my.cpp file from include
folder
#include “my.h” includes my.h file from current working
folder
#include “myfolder/abc.h” includes abc.h file from the myfolder which
is available in current working folder

From the above usage-table we can see that #include is used with two options angular brackets (<>)and inverted commas (“”). When #include is written with <> it means we are instructing to include the files from the include path defined in the compiler settings which is generally the include folder from the compiler. When #include is written with “” it means we are instructing to include a file: first the current folder is checked and if it is not found there, then the include folder of the compiler is checked.

Take a look at a simple example. Save the following code in a file called main.c:


#include<stdio.h>
#include "header.h"

int main() {
	
	printf("The variable from the header file: a = %d", a);
	return 0;
}

Then save the code below in a file called header.h and place it in the same directory as main.c:


#ifndef __mynamespace__
	int a = 10;
#endif

The variable declared in the header.h file will be included in main.c, so we can use the variable in main().

Macro Definition Directives

These are used to define macros, which are one, or more program statements (like functions) and they are expanded inline. (Expanded inline means they are substituted at the place of macro call unlike functions in which the execution pointer moves to the function definition.).

There are two directives for Macro Definition:

  • #define – Used to define a macro
  • #undef – Used to undefine a macro (The macro cannot be used after it is undefined.)

Take a look at the example, which is using include directive and some macro definition directives:


#include <iostream>
using namespace std;

#define PI 3.14

#define SQR(X) ((X)* (X))
#define CUBE(y) SQR(y)* (y) 

int main(int argc,char *argv[])
{
	int radius; 

	cout << endl << "Enter Radius of the Circle:"; cin >> radius;
	cout << endl << "Area of the Circle is: " << PI * SQR(radius); 

	#undef PI
	//It is now	invalid to use PI, thus we cannot use the next line.
	//cout << endl << "Perimeter  of Circle is : " <<  2 * PI * radius;

	cout << endl << "Area of the Sphere of Radius " << \
		radius << " is: " << 4/3.0 * 3.14 * CUBE(radius);
}

The above example illustrates the following:

  • We do not terminate the macros using (;)
  • Macros can be parameterized
  • Macros can be dependent on other macros (must be defined before they are used.)
  • Macros are customarily written in capital letters to avoid confusion between macro and functions. (this is not a rule)
  • Parameters are enclosed in () to avoid the ambiguity arising due to operator precedence. For instance in the example above we call SQR(4+3). This statement will be expanded as (4+3) * (4+3).
  • Directives are helpful whenever things are prone to changes and are used at many places in one program. Changing the directive value at the top will cause the corresponding changes at all the places in the program.

If the directive requires use of more than one line then it can be continued in the next line after placing ‘\’ at the end of the first line.

Take a look at the following example:


	#include <iostream>
	using namespace std;

	#define greater(m,n)(m>n) ? (m)	\
			: (n);

	int main(int argc, char *argv[])
	{
		int number1, number2;

		cout << endl << "Enter two numbers:";

		cin >> number1 >> number2;

		int g = greater(number1, number2);
		cout << endl << "Greater of the two numbers is: " << g;
	}

Conditional Compilation Directives

Conditional Compilation Directives these are used to execute statements conditionally for:

  • Executing the code on different machine architectures.
  • Debugging purposes.
  • Macros can be dependent on other macros (must be defined before they are used.)
  • Evaluating codes, which are to be executed depending upon the requirements of the programmer.

The following directives are included in this category:

  • #if
  • #elif
  • #endif
  • #ifdef
  • #ifndef

Note: These macros are evaluated on compile time. Therefore they can only use the predefined macros or literals. Most compilers do not support the use of variables with these directives.


#include <iostream>
using namespace std;

#define US 0
#define ENGLAND 1
#define NETHERLANDS 2

//We define Netherlands as country, then we get Euro.
//If we define England we get pounds and so on.
#define CURRENCY NETHERLANDS

int main(int argc, char *argv[])
{
	#if CURRENCY == US
		char acurrency[] = {"Dollar"};
		#define CHOSEN US
	#elif CURRENCY == ENGLAND
		char acurrency[] = { "Pound" };
		#define CHOSEN ENGLAND
	#elif CURRENCY == NETHERLANDS
		char acurrency[] = { "Euro" };
		#define CHOSEN NETHERLANDS
	#else
		char acurrency[] = {"Euro"};
	#endif

	// If CHOSEN is not defined, then we get default.
	#ifndef CHOSEN
		cout << endl << "Using Default Currency " << acurrency;
	#else
		cout << endl << "Chosen Currency " << acurrency;
	#endif
}

Other Directives

The following directives are the “other” directives:

  • #error
  • #line
  • #pragma

#error

When the #error directive is found the program will be terminated and the message (that is given after the #error statement) will be used in the compilation error that is given by the compiler.
Take a look at an example:


	#ifndef __cplusplus
	#error Compilation Error: A C++ compiler is required to compile this program!
	#endif

The __plusplus macro is by default defined by most C++ compilers. So if this macro is not found, during compilation, then the compilation is aborted and the message (Compilation Error: A C++ compiler is required to compile this program!) is printed for the user.

#line

The #line directive is used to change the value of the __LINE__ and __FILE__ macros. (Note: the filename is optional.) The __LINE__ and __FILE__ macros represent the line being read and the file being read.


	#line 50 "myfile.cpp"

This will set the __LINE__ to 50 and __FILE__ to myfile.cpp

#pragma

The #pragma directive is used to allow suppression of specific error messages, manage heap and stack debugging, etc. These are compiler specific directives. (Check your compiler documentation for the #pragma lines you can use.)

For Example “#pragma inline” statement indicates the assembly code is available in the code.

If the directive is unavailable in an implementation the statement is ignored.

Predefined Macros

__LINE__

An integer that gives the line number of the current source file being compiled.

__FILE__

A string that gives the name of the source file being compiled.

__DATE__

A string that gives the date, in the form “Mmm dd yyyy”, when the compilation process began.

__TIME__

A string constant that gives the time at which the preprocessor is being run. The string constant looks like “22:05:02″ and contains eight characters. If the compiler cannot determine the current time, it will give a warning message and __TIME__ will be expanded to “??:??:??”. Note: the warning will only be given once per compilation.

__STDC__

Forces the use of standard C/CPP codes only in the program.

__cplusplus

Contains a 6 digit number to indicate that the compiler is based on the standards, otherwise it contains 5 or fewer digits.

__ASSEMBLER__

This macro is defined with a value of 1 when preprocessing assembly language.

__OBJC__

If this macro is defined with a value of 1 then the Objective-C compiler is in use. This macro can be used to test whether a header file is compiled by a C compiler or an Objective-C compiler.

That is all for this tutorial.

This entry was posted in C++ Tutorials. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed. Tweet This! Tweet This! or use to share this post with others.

There are currently 3 responses to “C++ Preprocessor Directives”

Why not let us know what you think by adding your own comment!

  1. samba on January 23rd, 2013:

    good

  2. Zwergsocke on April 27th, 2014:

    nice work ;)
    but I belive you made a mistake with the “Predefined Macros” I think the macro __TIME__ should give you the Time when the compilation process began and not the name of the source file….. :)

  3. admin on April 27th, 2014:

    @Zwergsocke, THX I’ve changed the copy/paste error. The __TIME__ macro is now correct!