Preprocessor directives C and C++ :#include ,#if ,#ifndef ,#define ,#endif ,#else ,#undefine, #error, #line, #pragma


Preprocessor directives of C and C++

There are certain keywords in C and C++ with the character ‘#‘ attached in front of them.These keyword with the character ‘#‘ are known as preprocessor directives.The code or statement that follows preprocessor directives are always processed before the actual compilation of the file begins.This processing of preprocessor directives are known as preprocessing and it usually involves three main activity:

i)Inclusion of the header’s file content and source code file .
ii)Macro code substitution and
iii)Executing conditional compilation.

After preprocessing-after the three activities is carried out,the source code is converted to a new file known as translation unit.Using this file the compiler can start compiling the program to finally give the product known as executable file or binary file(.exe file).There are some steps involve between getting the .exe from the translation unit but I won’t be discussing the steps here.We will discuss only how to use the preprocessor directives,but again the macro part will be discuss in another post cause it will get quite lengthy if I combine the three topics in one post.


#include” directives

When you were starting out to write the first program “Hello world” in C++, I am sure you have come across this preprocessor directives and wondered “what the heck is this?”.Well I am not surprised cause I too felt the same once but I can assure you,your ignorance is about to go away.In your first program you might have come across a statement.

#include <iostream>

We usually interpret this statement as including the header’s file content: header’s file refer to any file enclosed between < >(angle bracket) or ” “(double quotation);their difference will be explained shortly after.When the compiler come across this directives and the file name it will try to include the member function or any other directives (like typdef,#define …) or const found inside the file in your program because it knows that the content from this file will be utilized in your program.Basically #include does nothing but simply command the compiler to add the content found inside the header’s file to the main source file.Simple isn’t?

The header’s file is usually written inside the opening and closing angle bracket(< >) but sometimes we are compel to write the header’s name under “”(double quotation).The reason behind this difference is quite simple.When you make a new library of your own say “mylib.h” and “mylib.cpp”,you might keep these two files in the directory where your main.cpp file is present.I usually keep my program in the directory “c:/my_program/…” so suppose, if I am making a program -first_program(the name of my program) ,the main.cpp will be present in the directory “c:/my_program/first_program” and the library file “mylib.h” and “mylib.cpp” will be also found in that directory(assuming they are kept in that directory).To call the function present in the new library I will have to write #include “mylib.h” not #include <mylib.h> in the main.cpp.Using the double quotation tell the compiler to search for the file mylib.h in the directory “c:/my_program/first_program” not in the standard directory which is usually “C:/CodeBlocks/MinGW/include/” where all the standard C++ header’s file are present.If you want to use the standard syntax to include the file-“#include ” transfer the file “mylib.h” to the directory “C:/CodeBlocks/MinGW/include/”,also note do not forget to change the ” “ in mylib.cpp to < >(angle bracket) while including the mylib.h file.An illustrated program is shown below.

///mylib.h file found in “C:/CodeBlocks/MinGW/include/”

#ifndef MYLIB_H_INCLUDED
#define MYLIB_H_INCLUDED

#include <string>

using namespace std ;

string append(string str_first ,string str_second );

#endif // MYLIB_H_INCLUDED

The next file is mylib.cpp file found in the same directory as the main.cpp.

#include <mylib.h>

using namespace std;

string append(string str_first ,string str_second )
{
return str_first+str_second ;
}

 
The main.cpp file
 

#include <iostream>
#include <mylib.h>

using namespace std;

int main( )
{
string s1=”Uzumaki ” , s2=”Naruto”;
cout<< append(s1,s2) ;

return 0;
}

 
The difference between ” “ and < > is the first represent the current directory while the second represent the standard directory.So when the compiler come across the double quotation or the opening and closing angel bracket(< >),it simply searches for the file in their concerned directories.





The conditional directives

The directive “#include” is seen in every source code of a program and it’s function seem to be very specific-to include the header’s file content.There are some directives which you may come across in a source code and which you will come across very(very) often in a library file(.h file).Such directives are known as conditional directives and they are ::

  #if
  #elif
  #else
  #endif

These directives can exert authority over certain codes that should be made available for compilation in some specific compiler and which should not on other compiler.They are known for their conditional property but their uses is not limited to exerting condition,it can vary depending on how you implement it.Of course their uses in varying implication will not be kept in a mystery and will be discussed in detail.But before we do that let us see the proper syntax that should be applied while using them and which programming entity goes with them.

If you look at the names of the directives #if , #elif , #else they resemble with the execution control statements if(),elseif() and else().Fortunately their behavior are also similar.But the statement #endif on the other hand,holds no significant properties and it simply signify the end of #if directives(or region).Like the execution control statement the conditional directives require a token that gives either true or false value and depending on that the code or macros belonging to the directive is executed.Consider the simple program below.

#define _NUMERAL 90
#define _TEST_VALUE 100

int main( )
{
#if _NUMERAL
  cout<< _NUMERAL ;
#endif ///Ending the #if region

#if _NUMERAL >= _TEST_VALUE
  cout<< _NUMERAL << “>=” << 100 << endl;
#elif _NUMERAL <= _TEST_VALUE
  cout<< _NUMERAL << ” <=” << 100 << endl ;
#else
  cout<< _NUMERAL
#endif ///End of code

#if defined(_NUMERAL)
  cout<< _NUMERAL << endl ;
#endif

cin.get( );
return 0 ;
}

The macro _NUMERAL is interpreted as true if it is not 0,this implies the macro _NUMERAL is true in the first #if directive and hence the value of _NUMERAL is outputted.In the third #if statement defined() is used to check whether the macro _NUMERAL has been defined/or exist.Using defined( ) does not check for the value assigned to the macro and so it does not check for true or false ,it simply checks whether the macro _NUMERAL exist or not.If it exist it will be taken as true otherwise false.You can use defined() to check for any existing macro whether a value is assigned to it or not.But if you want a more complex statement like comparing two macros value: _NUMERAL >= _TEST_VALUE to be used as conditional expression,do not use defined( ) because you will get an error.Consider another program below.

#define _NEW
#define _OLD 0

int main( )
{
#if _NEW   ///error : no value assigned
  cout<< _NEW ;
#endif

#if defined(_NEW)   // Work absolutely fine
  cout<< “_NEW defined \n” ;
#endif

#if defined( _DUDE)   //error : no _DUDE macro exist
  cout<< “_DUDE” ;
#endif

#if defined(__GNUC__)   //works fine,this macro come with the Code::blocks compiler so it’s true if you are using it
  cout<< __GNUC__ ;
#endif

cin.get( ) ;
return 0 ;
}

There are many macros like __GNUC__ which is a compiler specific macros defined only for the GNU GCC compiler, Visual Studio also have their own macros defined for it’s compiler,you can Google up to find more such macros and their uses.The use of conditional directives shown above is their general usage and little worth mentioning.They have a more noteworthy uses which can help a great deal in making our code/library robust.Some of these important uses are discussed below.


 


Choosing a compatible code for a specific compiler

Suppose you want to make a library(in C++) that can be compiled using both GNU GCC compiler and Visual studio compiler or more specifically you want to choose over which macros to defined and which to not when using a specific compiler.The solution is simple,you will use conditional directives to choose between the compiler and define the required macros.The code will look something like this.

#if defined(__cpluspluc)   ///this macros is defined for all C++ compiler
  #if defined(__MINGW32__)   ///__MINGW32__ is defined only in GCC compiler
  …  ///defined your macros or include your code here

  #elif defined(_MSC_VER)   ///_MSC_VER is defined only in Visual Studio compiler
 …   ///defined your macros or include your code here
#endif

The concept of implementation is simple here-check for macros defined only in the specific compiler and execute the code for that compiler,say if you are compiling in GCC compiler __MINGW32__ is already defined(and is defined only in GCC compiler),so the expression “defined(__MINGW32__)” renders true and the code or macros under that #if statement is executed.The same happened when the file is compiled in Visual Studio,since _MSC_VER is defined only in VS compiler this time the expression “defined(_MSC_VER)” becomes true and the code under #elif directive is compiled.The compilation need not be limited for just two compilers you can extend to other compiler by using the suitable macros defined only for that compiler.There is a more detail explanation for using libraries with different compiler here
http://gernotklingler.com/blog/creating-using-shared-libraries-different-compilers-different-operating-systems/


When using extern “c” to prevent name mangling.

Sometimes in your C++ program you might want to call a function written in C or you may want to use a C library compiled using C compiler.The standard norm of function name used in C and C++ object file are different.In C++ program suppose you have a function name get_value(), in an object file the name of this function is changed to something else say “abcdef()” (the way this names are changed depend on the compiler).This system of compiler changing the names of the function is known as name mangling.

One thing you should know is that name mangling occurs only for C++ function.That means if a function say getWidget() is defined in C,since there is no name mangling in C the object file containing that function will have it’s name as getWidget().If we try to call the getWidget() function in C++ program what happens is that the name of that C function will be mangled and so calling that function from the C object file is not possible as the compiler cannot find any function with that mangled name.To allow the call of C function in C++ program we usually use the conditional directives to signal the compiler that the functions declared are C function and their names should not be mangled .An example code is given below.

*Note:You can use the code given below either in main.cpp or in any library file where these functions are called.

#ifdef _cplusplus   ///same as #if defined(__cplusplus)
exntern “c” {
#endif

void getWidget( ) ; //C function
string widgetName( ) ; //C function

#ifdef __cplusplus
}
#endif

The function getWidget() and widgetName() names will will remain as it is in the C++ object file after it is compiled.The compiler can now call those function from the C object file containing those function with giving any reason to complain.





Commenting out a section of code

If you have written a library,sometimes certain situation compels you to abandon certain parts of your code or a case may arise which let you think that the code should be made available in the next version of your library.In this case deleting the whole code seems needless,so instead what you would prefer is commenting out the code.This is a better option than deleting because you wouldn’t have to rewrite the whole code again in the future.The simplest way for doing this in your library file or any other file is using the conditional directives #if.

#if 0   ///this is false so the code is not executed.
…   ///your code
#endif

Since 0 will always render false the code under the #if directive is always left out when compiling the program.


The #ifndef , #define directives

If you look at any header’s file (.h file) of a library before any real code is written you will always see the directives #ifndef followed by #define and at the end of the code #endif is added.The directive #ifndef meansif not defined,and it’s task is to check if a macro has been defined or to check if the macro exist.If the macro does not exist then the next line is executed if the macro exist nothing is done.This directive and the other directives comes in handy while writing a header’s file,but how?.Consider a header’s file name limits.h in this file the directives are written in the form as shown below.

#ifndef _LIMITS_H_
#define _LIMITS_H_

…   ///your code

#endif   /* _LIMITS_H_ */

The directives #ifndef plays a very important role in a header’s file.It always tries to prevent multiple inclusion of the content of the file whenever the compiler comes across #include <limits.h> in multiple files being compiled,but how does the directive do it?.Consider that you have included <limits.h> in your main.cpp file so when compiling if the compiler come across the directives #ifndef _LIMITS_H_ for the first time it will check if the macro _LIMITS_H_ exists.Since the macro does not exist the next directive “#define _LIMITS_H_” will define the macro _LIMITS_H_ and the content found in the remaining parts of the file is added to your main.cpp file. Suppose another library file say my_lib.h also include the file <limits.h> .The compiler after including the file my_lib.h it will try to include the file limits.h again because ” #include <limits.h> ” was also found in my_lib.h.This time what happen is the compiler in trying to include the file limits.h come across the directive #ifndef _LIMITS_H_ but since _LIMITS_H_ had already been defined,so #ifndef _LIMITS_H_ yields false.Now the compiler has no choice but to not include the file.Hence multiple inclusion of the file is prevented.

If the directives were not written then the compiler will try to include the library file whenever it come across “#include <limits.h>” in another file and this will give you an error.To illustrate the case when an error occurs consider the two library files written without the directives.The first file is header1.h and it’s content is shown below.

//header1.h

#include “header2.h”

typedef long long LL ;

 
The second library header’s file is header2.h.
 

//header2.h

#include “header1.h”

LL increment(LL val)   //LL is from header1 typedef
{
return ++val ;
}

 
The last file is the main.cpp file.
 

#include <iostream>
#include “header2.h”

using namespace std;

int main( )
{
cout<< increment(90 ) ;   ///call from header2.h file

cin.get() ;
return 0 ;
}

Try running the program with the library files content as shown above you will get an error undoubtedly.In the main.cpp, header2.h is included so it’s content is loaded by the compiler and also the header2.h file include the header’s file header1.h so it’s content is also loaded.But inside header1.h the header2.h file is included so the compiler tries to load again it’s content(header2.h) but to no avail cause it’s content is already added.To this attempt in trying to include the content of header2.h multiple time the compiler will generate an error.From this the conclusion that can be drawn is never forget to write the directives #ifndef ,#define and #endif in your header’s file.



Other directive: #line, #error , #undef , #pragma

There are some other directives that might be useful in some ways and may not in other ways.They are explained below.

#line

The #line directives is used for changing the number of the line.This directive does not require a macro but instead it accept a literal(a value).Suppose the value associated with the directive is 90-“#line 90“,then the line next to the directive will have a line number 91.Consider the program below.

Link

int main( )
{
#line 70
 cout<< __LINE__ ;   ///this macros gives the line number

cin.get();
return 0 ;
}

Run the program and see if the output of the line number match with the value shown in the left margin of the line number column in your IDE editor or does it give 71.

#error

#error directives is used to give an error message when the compiler encounters an error.This directive is mainly used for debugging purpose.

#undef

The function of #defined directive is to bring an existence of a new macro.The #undef
does the opposite of #define.So #undef takes away the existence of a macros.

#define __RISE

int main( )
{
#undef __RISE

#if defined(__RISE)
  cout<< “__RISE is defined \n” ;
#else
  cout<< “__RISE is not defined \n” ;
#eindif

cin.get( ) ;
return 0 ;
}

You can run the program to witness the function of #undef directives.

#pragma

#pragma is implemetation-defined directive through which we can pass instructions that are meant for the compiler.One use of #pragma that you will come across if you open the _mingw.h(present in code::blocks IDE) header file is.

#pragma GCC system_header

The directive #pragma tell the compiler that the include file starting from the next to the directives to be considered as system header.What is system header? that you might wanna check up in the Google.

Well that’s the description of all the directives found in C and C++.I am sure nothing is left out if I did so comment below.And the macro which is part of the #define directive is discussed in another post so do check it out.


Related Link

->Using Ellipsis (…) and initialization_list
 
->C++ Execution control statement:if() else , do while() , while() , for() , switch() case.