Navigation



1.10 — A first look at the preprocessor

The preprocessor is perhaps best thought of as a separate program that runs before the compiler when you compile your program. It’s purpose is to process directives. Directives are specific instructions that start with a # symbol and end with a newline (NOT a semicolon). There are several different types of directives, which we will cover below. The preprocessor is not smart — it does not understand C++ syntax; rather, it manipulates text before the compiler gets to it.

Includes

You’ve already seen the #include directive in action. #Include tells the preprocessor to insert the contents of the included file into the current file at the point of the #include directive. This is useful when you have information that needs to be included in multiple places (as forward declarations often are).

The #include command has two forms:
#include <filename> tells the compiler to look for the file in a special place defined by the operating system where header files for the runtime library are held.
#include "filename" tells the compiler to look for the file in directory containing the source file doing the #include. If that fails, it will act identically to the angled brackets case.

Macro defines

Macro defines take the form:

#define identifier replacement

Whenever the preprocessor encounters this directive, any further occurrence of ‘identifier’ is replaced by ‘replacement’. The identifier is traditionally typed in all capital letters, using underscores to represent spaces.

For example, consider the following snippet:

#define MY_NAME  "Alex"

cout << "Hello, " << MY_NAME << endl;

The preprocessor converts this into the following:

#define MY_NAME  "Alex"

cout << "Hello, " << "Alex" << endl;

Which, when run, prints the output Hello, Alex.

#defines used in this manner have two important properties. First, they allow you to give a descriptive name to something, such as a number.

For example, consider the following snippet:

int nYen = nDollars * 122;

A number such as the 122 in the program above is called a magic number. A magic number is a hard-coded number in the middle of the code that does not have any context — what does 122 mean? Is it a conversion rate? Is it something else? It’s not really clear. In more complex programs, it is often impossible to tell what a hard-coded number represents.

This snippet is clearer:

#define YEN_PER_DOLLAR  122
int nYen = nDollars * YEN_PER_DOLLAR;

Second, #defined numbers can make programs easier to change. Assume the exchange rate changed from 122 to 123, and our program needed to reflect that. Consider the following program:

int nYen1 = nDollars1 * 122;
int nYen2 = nDollars2 * 122;
int nYen3 = nDollars3 * 122;
int nYen4 = nDollars4 * 122;
SetWidthTo(122);

To update our program to use the new exchange rate, we’d have to update the first four statements from 122 to 123. But what about the 5th statement? Does that 122 have the same meaning as the other 122s? If so, it should be updated. If not, it should be left alone, or we might break our program somewhere else.

Now consider the same program with #defined values:

#define YEN_PER_DOLLAR  122
#define COLUMNS_PER_PAGE  122

int nYen1 = nDollars1 * YEN_PER_DOLLAR;
int nYen2 = nDollars2 * YEN_PER_DOLLAR;
int nYen3 = nDollars3 * YEN_PER_DOLLAR;
int nYen4 = nDollars4 * YEN_PER_DOLLAR;
SetWidthTo(COLUMNS_PER_PAGE);

To change the exchange rate, all we have to do is make one change:

#define YEN_PER_DOLLAR  123
#define COLUMNS_PER_PAGE  122

int nYen1 = nDollars1 * YEN_PER_DOLLAR;
int nYen2 = nDollars2 * YEN_PER_DOLLAR;
int nYen3 = nDollars3 * YEN_PER_DOLLAR;
int nYen4 = nDollars4 * YEN_PER_DOLLAR;
SetWidthTo(COLUMNS_PER_PAGE);

Now we’ve updated our yen conversions, and don’t have to worry about inadvertently changing the number of columns per page.

While #define values are a huge improvement over magic numbers, they have some issues of their own, which we will talk more about later when we get into variables and scoping issues.

You can undefine a previously defined value by using the #undef preprocessor directive.

Consider the following snippet:

#define MY_NAME "Alex"
cout << "My name is " << MY_NAME << endl;
#undef MY_NAME
cout << "My name is " << MY_NAME << endl;

The last line of the program causes a compile error because MY_NAME has been undefined.

Conditional compilation

The conditional compilation preprocessor directives allow you to specify under what conditions something will or won’t compile. The only conditional compilation directives we are going to cover in this section are #ifdef, #ifndef, and #endif.

The #ifdef preprocessor directive allow the preprocessor to check whether a value has been previously #defined. If so, the code between the #ifdef and corresponding #endif is compiled. If not, the code is ignored.

Consider the following snippet of code:

#define PRINT_JOE

#ifdef PRINT_JOE
cout << "Joe" << endl;
#endif

#ifdef PRINT_BOB
cout << "Bob" << endl;
#endif

Because PRINT_JOE has been #defined, the line cout << "Joe" << endl; will be compiled. Because PRINT_BOB has not been #defined, the line cout << "Bob" << endl; will not be compiled.

#ifndef is the opposite of #ifdef, in that it allows you to check whether a name has NOT been defined yet.

#ifndef PRINT_BOB
cout << "Bob" << endl;
#endif

This program prints “Bob”, because PRINT_BOB was never #defined.

Header guards

Because header files can include other header files, it is possible to end up in the situation where a header file gets included multiple times. For example, consider the following program:

add.h:

#include "mymath.h"
int add(int x, int y);

subtract.h:

#include "mymath.h"
int subtract(int x, int y);

main.cpp:

#include "add.h"
#include "subtract.h"

When we include add.h, it brings in both mymath.h and the prototype for add(). When we include subtract.h, it brings in both mymath.h (again) and the prototype for subtract(). Consequently, all the contents of mymath.h will have been included twice, which will cause the compiler to complain.

To prevent this from happening, we use header guards, which are conditional compilation directives that take the following form:

#ifndef SOME_UNIQUE_NAME_HERE
#define SOME_UNIQUE_NAME_HERE

// your declarations here

#endif

When this header is included, the first thing it does is check whether SOME_UNIQUE_NAME_HERE has been previous defined. If this is the first time we’ve included the header, SOME_UNIQUE_NAME_HERE will not have been defined. Consequently, it #defines SOME_UNIQUE_NAME_HERE and includes the contents of the file. If this is not the first time we’ve included the header, SOME_UNIQUE_NAME_HERE will already have been defined from the first time the contents of the header were included. Consequently, the entire header will be ignored.

All of your header files should have header guards on them. SOME_UNIQUE_NAME_HERE can be any name you want, but typically the name of the header file with a _H appended to it is used. For example, add.h would have the header guard:

#ifndef ADD_H
#define ADD_H

// your declarations here

#endif

Even the standard library includes use header guards. If you were to take a look at the iostream header file from Visual Studio 2005 Express, you would see:

#ifndef _IOSTREAM_
#define _IOSTREAM_

// content here

#endif
1.10a — How to design your first programs
Index
1.9 — Header files

67 comments to 1.10 — A first look at the preprocessor

  • [...] using literal constants that aren’t 0 or 1. For more detail, you can review the section on magic numbers, and why they are a bad [...]

  • [...] 2007 Prev/Next Posts « 1.8 — Programs with multiple files | Home | 1.10 — A first look at the preprocessor » Sunday, June 3rd, 2007 at 9:29 [...]

  • GovZ

    Hello guys,

    I just wanted to ask if you have enough room for :

    #if defined(macro_name) || defined (macro_name2)

    in this tutorial :) I use this quite a lot in coding. Is this a part of the standard by the way?

    I have read chapter 0 up to this part and plan to read more. Thanks and more power :)

  • GovZ, as far as I know, that is an official part of the preprocessor. You should also be able to use && to test whether multiple symbols are defined at the same time:

    #if defined (symbol_a) && defined (symbol_b)

    I didn’t cover these specific concepts in this tutorial because I don’t even cover what the || and && symbols mean until section 3.6. This is just supposed to be a quick introduction, not a full preprocessor tutorial. :)

    There are quite a few other neat things the preprocessor can do that I don’t (and don’t plan to) cover in this tutorial. If you are interested in learning more, there are quite a few preprocessor documents that are publicly available. Here’s one.

  • billerr

    This might be a dumb question, but what exactly is the purpose of:

    #define [identifier]

    i.e. a #define without any replacement?

    Is it useful mostly in header guards?

  • Jason

    I’m not absolutely sure but from what I’ve read here and a book I have, I believe you are correct about it only being for the header guards when there is no replacement.

  • Billerr, You can use such defines for several reasons. Header guards are the primary one. However, it can be useful to define code that only executes when certain #defines have been set. For example, you might do something like this:

    #ifdef _DEBUG
    cout < < nDebugVariable << endl;
    #endif
    

    This would only print out nDebugVariable if the program was compiled with the _DEBUG symbol #defined. You might turn this symbol on when compiling a version for development or testing, but turn it off for the release version.

    In a game I wrote, I used a #define to toggle whether the game generated random dungeons (for the release version) or a special debug level (for testing/development). I could toggle between the two by commenting/uncommenting the #define and recompiling.

  • [...] 2007 Prev/Next Posts « 1.10 — A first look at the preprocessor | Home | News — New site functionality » Sunday, June 3rd, 2007 at 1:01 [...]

  • David

    I have a quick question… what is the benefit of using define as opposed to simply initilializing the variable?

    What is the difference between

    #define COLUMNS_PER_PAGE  122

    and

    int COLUMNS_PER_PAGE = 122 
    • Personally I don’t think there is any reason to use #define this way.

      The only place I use #defines is when #defining symbols to use with #ifdef or #ifndef. You can’t use regular variables for those.

    • markdj

      I don’t know if there’s another benefit, but it does let you and anyone else looking at the code that it’s a constant and not going to be able to be changed throughout the program.

  • weirdolino

    Hi, just wanted to point out a little (somewhat misleading) mistake in the page. Close to the top, where you explain the two forms of the #include command the first form should be &ltfilename&rt. It doesn’t display filename at all, at least in my browser (opera), since it’s in angle brackets instead of escape codes and the browser thinks it’s supposed to be an html tag.

    Awesome tutorial, the best i’ve read so far. Thanks a lot for sharing your knowledge.

    [ Fixed. Thanks for letting me know. -Alex ]

  • Ok the coding you provided for the header guard is going to be VERY helpful. Thanks for that.

  • arvind

    Great Article , Thanks Alex

  • adam

    Why can’t you make your whole program in a header file then just have #include “headerfile.h” in the main.cpp and compile? What can and can’t you put in a header file instead of a .cpp file?

    • You can put almost anything in a header file (there are a few exceptions). Thus, you could write your whole program in a header file and #include it into a .cpp, but if you’re going to do that, why not just skip the header file and put the code in the .cpp in the first place?

  • Ray

    I have a question about header guards…borrowing from the above examples if we define:

    add.h

    #ifndef ADD_H
    #define ADD_H  
    
    #include "myMath.h"
    int add(int a, int b)
    
    #endif
    

    subtract.h

    #ifndef SUBTRACT_H
    #define SUBTRACT_H  
    
    #include "myMath.h"
    int subtract(int a, int b)
    
    #endif
    

    and with main.cpp including both:

    #include "add.h"
    #include "subtract.h"
    

    won’t we still have the exact same problem, ie add.h and subtract.h both still bring in a copy of myMath.h and the compiler will still complain?

    Thanks,
    Ray

    PS-Thanks for putting this tutorial up, its easily the best I’ve seen on the web

    • Ray

      Never mind i just figured it out…if we use the header guards for every header, in the above example this will include the myMath.h, then when we try to bring in the myMath.h headera second time, MYMATH_H will already be defined (from the first time it was brought in) and the #ifndef statement will not allow for whatever is in myMath.h to be brought in a second time…thats pretty neat.

      Thanks again
      Ray

      [ You got it. -Alex ]

      • Noha

        I just paid attention that your question is close to the question I posted.
        You say “#ifndef statement will not allow for whatever is in myMath.h to be brought in a second time”, you mean that #ifndef MYMATH_H is needed before every #include of add.h and subtract.h?

        • Matt

          The idea is that myMath.h would have a header guard of MYMATH_H, after the first include it would define MYMATH_H and allow the first myMath.h to compile. When it was included the second time MYMATH_H would already be defined from the first call to myMath.h, so it would not compile the second instance of the include.

          tl;dr: The header guard for myMath.h (MYMATH_H) is not needed in add.h or subract.h, it’s needed in myMath.h

  • csvan

    Alex,

    I think it would be very helpful to add a concrete example of header guards in action at the end of this page, based on the headers you previously declared. As this is a somewhat confusing concept depending on how you approach it, having a concrete, documented example would drive through a very forceful explanation.

    Thanks for all your hard work!

  • Noha

    Hi Alex,
    In the example you gave about #include “add.h” and #include “subtract.h”, where we use #ifdef/#ifndef and #andif?
    I guess it should be in main.cpp but don’t know where exactly and how :-/

    • Cooper

      Thanks, Alex! your site is a real help! I wrote a sample temperature converter program with the site’s help!

      Noha, will this help?

      #ifndef WRITEANSWER
      #define WRITEANSWER
      
      void WriteAnswer(int x);
      
      #endif
  • Prayrit

    I really don’t understand the header guard example given here. Would the mymath.h have to be taken out of the add and subtract headers, and then put into the main class with another header guard?

    • Prayrit

      Actually I think I got it. Tell me if I’m right.

      mymath.h

      #ifndef MYMATH_H
      #define MYMATH_H
      
      // your declarations here
      
      #endif
      

      add.h

      #ifndef ADD_H
      #define ADD_H
      
      #include "mymath.h"
      int add(int x, int y);
      
      #endif
      

      subtract.h

      #ifndef SUBTRACT_H
      #define SUBTRACT_H
      
      #include "mymath.h"
      int subtract(int x, int y);
      
      #endif
      

      main.cpp

      #include "add.h"
      #include "subtract.h"
      
      • baldo

        Yes you got it. This should be the full example for header guards.

      • Rukshan

        Hi Alex,

        Thanks for sharing your knowledge. I have question about using headers. In lesson 1.9 you did not use
        #include “add.h” in the header file but when explaining header guards you used “mymath.h” in the header file. I’m sorry I’m confused. What’s the point of using “mymath.h” if its not defined.

        regards,
        Rukshan.

      • Rukshan

        Hi,

        Would you kindly write “// your declarations here” part to make it clear. Because I still don’t get the use of “mymath.h” here. Thanks a lot.

      • Rukshan

        Would you kindly write “// your declarations here” part to make it clear. Because I still don’t get the use of “mymath.h” here.

        • Trophy

          Wouldn’t you not need to add the header guards in add.h and subtract.h since the issue is with mymath.h being called twice and not the other two? Or is this just good form?

      • artxworks
        
        //mymath.h
        
        #ifndef MYMATH_H
        #define MYMATH_H
        
        // your declarations here
        
        #endif
        add.h
        
        #ifndef ADD_H
        #define ADD_H
        
        #include "mymath.h"
        int add(int x, int y);
        
        #endif
        subtract.h
        
        #ifndef SUBTRACT_H
        #define SUBTRACT_H
        
        #include "mymath.h"
        int subtract(int x, int y);
        
        #endif
        main.cpp
        
        #include "add.h"
        #include "subtract.h"
        

        I still don’t understand the mymath.h thing … can you give an example to what can be placed inside that header? than can be used by your add and subtract headers … I understand that by calling the mymath.h on both the add and subtract headers will prevent it being called on twice in the main function but I’m wondering what kind of equation can be placed there ….

      • artxworks
        
        //mymath.h
        
        #ifndef MYMATH_H
        #define MYMATH_H
        
        // your declarations here
        
        #endif
        add.h
        
        #ifndef ADD_H
        #define ADD_H
        
        #include "mymath.h"
        int add(int x, int y);
        
        #endif
        subtract.h
        
        #ifndef SUBTRACT_H
        #define SUBTRACT_H
        
        #include "mymath.h"
        int subtract(int x, int y);
        
        #endif
        main.cpp
        
        #include "add.h"
        #include "subtract.h"
        

        I still don’t understand the mymath.h thing … can you give an example to what can be placed inside that header? than can be used by your add and subtract headers … I understand that by calling the mymath.h on both the add and subtract headers will prevent it being called on twice in the main function but I’m wondering what kind of equation can be placed there ….

  • William

    First, thank you so much, Alex for your excellent tutorial. Having previously been a developer in Assembler, COBOL and C from the decade of the 80′s (left the field in 1990), I can truly appreciate the hard work and excellence you have shared with us all. I find your sight so far to be a wonderful opportunity for me to once again explore the world of programming thru C++.

    My question:
    These last two entries by baldo and Prayrit, baldo indicates that Prayrit’s code should be the full example for header guards. Since you did not reply, I assume you do agree.

    I also take note of your explanation that the compiler will check the function prototypes that have been declared via the add.h and subtract.h #includes against the function calls within the source code to resolve any syntactical errors and it will be the job of the linker to ensure that all the function calls are eventually defined.

    Having said all that, I am not quite sure of the purpose of ‘mymath.h’. The comment in the header file says “// your declarations here”. Is it additional math declarations (eg. division() or multiplication()prototypes)or was it supposed to be the ‘definitions’ for the add() and subtract() functions. I assumed it to be the latter.

    If mymath.h does in this particular case contain the definitions for add() and subtract(), then when it compiles, wouldn’t the compiler not only insert the add() and subtract() function prototypes for declaration within main.cpp but because of the #include of mymath.h within the add.h and subtract.h files, also insert the function definitions of add() and subtract() I assume to be located therin, thereby causing compiling errors?

    Finally, if mymath.h does not contain the definitions, then where are the definitions in this case, and what is mymath.h doing?

  • Student pairs are assigned a particular area on the grid and then walk through the area, taking detailed notes and looking for specific youth-related opportunities and services. ,

  • prabhakar

    i am confused by the explanation, “identifier’ and “replacement”. u have said [ define identifier replacement ]whereas in the example given to replace 122, i fail to understand this.
    the identifier is YEN_PER_DOLLAR and replacement is 122 as per the define mode GIVEN ABOVE.
    so how can 122 be replaced? by YEN_PER_DOLLAR?

    #define YEN_PER_DOLLAR 122
    int nYen = nDollars * YEN_PER_DOLLAR;

    I AM VERY NEW TO C++ SO BE CONSIDERATE AND EXPLAIN
    THANKS PRABHAKAR

  • prabhakar

    please treat my comment as cancelled prabhakar

  • iamone

    Hey Alex great tutorial!
    i was just wondering why #define Print_joe
    was not just #define joe?
    Doesn’t the word Print throw the whole thing off?
    This question has been really bugging me, any answer would be appreciated

    THANKS!

  • retro-starr

    Is there anything wrong with typing the headers in lowercase and with spaces (I still use underscores though)? I tested it out earlier when I was making another program that used a header and it still worked. If there’s nothing wrong, I stylistically like the lowercase.

  • this is just awesome teacher…made programming lot easier..thank u fellows..!

  • I’m confused, how does it know if the header has already been declared?
    For example, if it says

    #ifndef add_h

    in the header file, how does it know if add.h is declared since they are not the same?

    • Okay never mind. Correct me if I’m wrong:
      All the header files will have

      #ifndef SOME_UNIQUE_NAME_HERE
      #define SOME_UNIQUE_NAME_HERE
      
      // your declarations here
      
      #endif
      //stuff
      

      so that if the header is not included, then SOME_UNIQUE_NAME_HERE will not have been defined.
      “Your declarations here” will be the “include”‘s of headers, and “stuff” should be the code of the header? Thanks.

  • David

    I love this tutorial!!!

  • Eric

    I guess my question is: why would a header file need to include a different header file if all header files contain are declarations? Is this something you only encounter once you are writing bigger programs? I understand including header files in places where you are using functions defined in external files to avoid writing a ton of forward declarations, but can someone give me an example that wouldn’t be completely over my head of a header needing to include another header? Thanks!

  • Anand

    VERY NICE MATERIAL, LEARNED AND PERFORMED IN FIRST ATTEMPT. THANKS.

  • alienbeliever

    This tutorial is so well structured and understandable that it blows my mind. Thanks A LOT. It´s an outstanding work of love. KUDOS!

  • I noticed an ad to download Registry Mechanic on this page. If you consider getting that program, I think you should read this article before you do so: Do NOT clean the Windows registry.

  • Dominator_X

    Hi there! I want to know what is n stands for? For example int nYen2 = nDollars2

    I am trying to learn C++ whit your turorials but dont get a point for that. Thank you in advance!

  • lackadaisy

    I just wanted to leave a note saying this is the most amazing tutorial ever. I hated programming but I think I might start liking it quite a bit now because I finally understand it!

  • SWEngineer

    Simply well explained tutorial. Thanks a lot.

    I just spotted a small typo here:

    #Include tells the preprocessor……

    Shouldn’t #Include be #include with lowercase “i”?

  • YamNahar

    At this step
    #define MY_NAME “Alex”
    cout << "Hello, " << MY_NAME << endl;
    i get 2 errors:
    error C2143: syntax error : missing ';' before '<<'
    error C4430: missing type specifier – int assumed. Note: C++ does not support default-int
    what's wrong? I did something wrong, or was something wrong?

  • [...] avoid using literal constants that aren’t 0 or 1. For more detail, you can review the section on magic numbers, and why they are a bad [...]

  • [...] two parts. The first part is called a header guard, which is discussed in the next lesson (on the preprocessor). The second part is the actual content of the .h file, which should be the declarations for all of [...]

  • [...] two parts. The first part is called a header guard, which is discussed in the next lesson (on the preprocessor). The second part is the actual content of the .h file, which should be the declarations for all of [...]

  • [...] two parts. The first part is called a header guard, which is discussed in the next lesson (on the preprocessor). The second part is the actual content of the .h file, which should be the declarations for all of [...]

  • [...] avoid using literal constants that aren’t 0 or 1. For more detail, you can review the section on magic numbers, and why they are a bad [...]

  • Maverick95

    I’m failing to see why I need to use header guards with the IDE that I’m using.
    The code below I’ve used in Microsoft Visual C++ 2010 Express and it compiles without any complaints or errors.

    NumericOperations.h

    int add(int x, int y);
    int subtract(int x, int y);

    PrintAdd.h

    #include "NumericOperations.h"

    #ifndef PRINTADD_H
    #define PRINTADD_H

    void PrintAdd(int x, int y);

    #endif

    PrintSubtract.h

    #include "NumericOperations.h"

    #ifndef PRINTSUBTRACT_H
    #define PRINTSUBTRACT_H

    void PrintSubtract(int x, int y);

    #endif

    HeaderGuardTest.cpp

    #include "stdafx.h"
    #include "PrintAdd.h"
    #include "PrintSubtract.h"
    #include "KeyFunctions.h"

    I should note that all the functions above have been defined in .cpp files.

    My code compiles successfully, but I have included NumericOperations.h twice. Shouldn’t this give me an error?

    • The #ifndef ensures that everything required is initialized once and no more. When you load it the second time, the compiler sees that the variables and whatnot have been declared, so it does nothing.

  • [...] two parts. The first part is called a header guard, which is discussed in the next lesson (on the preprocessor). The second part is the actual content of the .h file, which should be the declarations for all of [...]

  • [...] avoid using literal constants that aren’t 0 or 1. For more detail, you can review the section on magic numbers, and why they are a bad [...]

  • Learner

    #include directives like these are also valid:
    #include “dir/file.h”
    #include “../file.h”

  • dice3000

    I believe that [ #pragma once ] serves the same purpose as header guards

  • [...] two parts. The first part is called a header guard, which is discussed in the next lesson (on the preprocessor). The second part is the actual content of the .h file, which should be the declarations for all of [...]

  • [...] avoid using literal constants that aren’t 0 or 1. For more detail, you can review the section on magic numbers, and why they are a bad [...]

  • Thanks so much for these tutorials. Wish I had found them years ago. So many basic things that I needed to understand the C++ examples I was reading at the time.

    You present at a good level of detail–enough examples, but not too long.

You must be logged in to post a comment.