Conditional compilation


One of the most powerful features of the preprocessor is the so-called conditional compilation this  means that portions of the code could be excluded in the actual compilation under the certain conditions. 

This means that your source could contain special code for, say, the ARM processor. Using conditional  compilation, this code could be ignored when compiling for all other processors. 
The preprocessor directives #ifdef, #ifndef, #if, #elif, and #else are used to control the 
source code. 

The #ifdef (#ifndef) directive includes a section if a preprocessor symbol is defined 
(undefined). 

Const and data hiding


In C++ when a member function returns a pointer which points to it’s member variable, there exists a possibility of the pointer address or the pointer value getting modified. This problem can be overcome by using the const keyword. An example illustrating this idea is given below

class Person
{
public:
Person(char* szNewName)
{
// make a copy of the string
m_szName = _strdup(szNewName);
};
~Person() { delete[] m_szName; };
const char* const GetName() const
{
return m_szName;
};
private:
char* m_szName;
};

In the above class the GetName() member function returns a pointer to the member variable m szName. To prevent this member variable from getting accidently modified the GetName() has been prototyped to return a constant pointer pointing to a constant value. Also the const keyword at the end of the function prototype states that the function does not modify any of the
member variables.

Don’t ignore API function return values


Most API functions will return a particular value which represents an error. You should test for these values every time you call the API function. If you don’t want want to clutter your code with error-testing, then wrap the API call in another function (do this when you are thinking about portability, too) which tests the return value and either asserts, handles the problem, or throws an exception. The above example of Open Data File is a primitive way of wrapping fopen with error-checking code which throws an exception if fopen fails.

Redefinitions, Redclarations , Conflicting types


Consider what happens if a C source file includes both a.h and b.h, and also a.h includes b.h (which is perfectly sensible; b.h might define some types that a.h needs). Now, the C source file includes b.h twice. So every #define in b.h occurs twice, every declaration occurs twice (not actually a problem), every typedef occurs twice, etc. In theory, since they are exact duplicates it
shouldn’t matter, but in practice it is not valid C and you will probably get compiler errors or at least warnings.

The solution to this problem is to ensure that the body of each header file is included only once per source file. This is generally achieved using preprocessor directives. We will define a macro for each header file, as we enter the header file, and only use the body of the file if the macro is not already defined. In practice it is as simple as putting this at the start of each header file: