2.10 — Introduction to the preprocessor

Translation and the preprocessor

When you compile your code, you might expect that the compiler compiles the code exactly as you’ve written it. This actually isn’t the case.

Prior to compilation, the code file goes through a phase known as translation. Many things happen in the translation phase to get your code ready to be compiled (if you’re curious, you can find a list of translation phases here). A code file with translations applied to it is called a translation unit.

The most noteworthy of the translation phases involves the preprocessor. The preprocessor is best thought of as a separate program that manipulates the text in each code file.

When the preprocessor runs, it scans through the code file (from top to bottom), looking for preprocessor directives. Preprocessor directives (often just called directives) are instructions that start with a # symbol and end with a newline (NOT a semicolon). These directives tell the preprocessor to perform specific particular text manipulation tasks. Note that the preprocessor does not understand C++ syntax -- instead, the directives have their own syntax (which in some cases resembles C++ syntax, and in other cases, not so much).

The output of the preprocessor goes through several more translation phases, and then is compiled. Note that the preprocessor does not modify the original code files in any way -- rather, all text changes made by the preprocessor happen temporarily in-memory each time the code file is compiled.

In this lesson, we’ll discuss what some of the most common preprocessor directives do.

As an aside...

Using directives (introduced in lesson 2.9 -- Naming collisions and an introduction to namespaces) are not preprocessor directives (and thus are not processed by the preprocessor). So while the term directive usually means a preprocessor directive, this is not always the case.


You’ve already seen the #include directive in action (generally to #include <iostream>). When you #include a file, the preprocessor replaces the #include directive with the contents of the included file. The included contents are then preprocessed (along with the rest of the file), and then compiled.

Consider the following program:

When the preprocessor runs on this program, the preprocessor will replace #include <iostream> with the preprocessed contents of the file named “iostream”.

Since #include is almost exclusively used to include header files, we’ll discuss #include in more detail in the next lesson (when we discuss header files in more detail).

Macro defines

The #define directive can be used to create a macro. In C++, a macro is a rule that defines how input text is converted into replacement output text.

There are two basic types of macros: object-like macros, and function-like macros.

Function-like macros act like functions, and serve a similar purpose. We will not discuss them here, because their use is generally considered dangerous, and almost anything they can do can be done by a normal function.

Object-like macros can be defined in one of two ways:

#define identifier
#define identifier substitution_text

The top definition has no substitution text, whereas the bottom one does. Because these are preprocessor directives (not statements), note that neither form ends with a semicolon.

Object-like macros with substitution text

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

Consider the following program:

The preprocessor converts the above into the following:

Which, when run, prints the output My name is: Alex.

We recommend avoiding these kinds of macros altogether, as there are better ways to do this kind of thing. We discuss this more in lesson 4.13 -- Const, constexpr, and symbolic constants.

Object-like macros without substitution text

Object-like macros can also be defined without substitution text.

For example:

Macros of this form work like you might expect: any further occurrence of the identifier is removed and replaced by nothing!

This might seem pretty useless, and it is useless for doing text substitution. However, that’s not what this form of the directive is generally used for. We’ll discuss the uses of this form in just a moment.

Unlike object-like macros with substitution text, macros of this form are generally considered acceptable to use.

Conditional compilation

The conditional compilation preprocessor directives allow you to specify under what conditions something will or won’t compile. There are quite a few different conditional compilation directives, but we’ll only cover the three that are used by far the most here: #ifdef, #ifndef, and #endif.

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

Consider the following program:

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

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

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

#if 0

One more common use of conditional compilation involves using #if 0 to exclude a block of code from being compiled (as if it were inside a comment block):

The above code only prints “Joe”, because “Bob” and “Steve” were inside an #if 0 block that the preprocessor will exclude from compilation.

This provides a convenient way to “comment out” code that contains multi-line comments.

Object-like macros don’t affect other preprocessor directives

Now you might be wondering:

Since we defined PRINT_JOE to be nothing, how come the preprocessor didn’t replace PRINT_JOE in #ifdef PRINT_JOE with nothing?

Macros only cause text substitution for normal code. Other preprocessor commands are ignored. Consequently, the PRINT_JOE in #ifdef PRINT_JOE is left alone.

For example:

In actuality, the output of the preprocessor contains no directives at all -- they are all resolved/stripped out before compilation, because the compiler wouldn’t know what to do with them.

The scope of defines

Directives are resolved before compilation, from top to bottom on a file-by-file basis.

Consider the following program:

Even though it looks like #define MY_NAME “Alex” is defined inside function foo, the preprocessor won’t notice, as it doesn’t understand C++ concepts like functions. Therefore, this program behaves identically to one where #define MY_NAME “Alex” was defined either before or immediately after function foo. For general readability, you’ll generally want to #define identifiers outside of functions.

Once the preprocessor has finished, all defined identifiers from that file are discarded. This means that directives are only valid from the point of definition to the end of the file in which they are defined. Directives defined in one code file do not have impact on other code files in the same project.

Consider the following example:



The above program will print:

Not printing!

Even though PRINT was defined in main.cpp, that doesn’t have any impact on any of the code in function.cpp (PRINT is only #defined from the point of definition to the end of main.cpp). This will be of consequence when we discuss header guards in a future lesson.

2.11 -- Header files
2.9 -- Naming collisions and an introduction to namespaces

209 comments to 2.10 — Introduction to the preprocessor

  • Harshul

    Why is their use not recommended, they are fast and capable of doing what small functions are expected to do???

    • Alex

      Function-like macros are full of gotchas and unexpected behavior that that's avoided by using normal functions, particularly when it comes to side effects.


      Seems harmless, right?

      But if you call it like this:

      You'd expect the result to be 4, but you actually get 6.

      This happens because ++n is copied into the macro before being evaluated, so your output statement becomes "std::cout << (++n) + (++n);" This sort of behavior is avoided using normal functions.

      • Shri

        The result is 5 if you have this program:

        • Hi Shri!

          Good observation.

          is an undefined operation, there is no standard way of evaluating this, so you'll get different results with different compilers. This is covered in a later lesson.

  • Harshul

    Wouldn't it be a more appropriate define for macro as given by gnu-
    "A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro."

    • Alex

      That definition would be appropriate if macros were strictly substitution-based. But function-like macros do a little more than replacement (even though we don't recommend their use).

  • Nyap

    I came across this on Stack Overflow:
    "Notably, it completely misses an introduction to the STL and the proper use of it. You barely see std::cout and std::string. There's no mention of <algorithm> that I could see of and no mention of the <vector> or <deque> or <map> which are the most commonly used containers in C++."
    Whats this? D:

    • Alex

      A professional race car driver might look at a drivers education course and criticise it for not teaching you how to drive race cars. But that's not really the point, is it?

      Some of these criticisms are fair, and have already been addressed in updates made over the last 5 years. Others (e.g. the omission of parts of the STL) miss the mark a bit. The point of this tutorial isn't to comprehensively cover every corner of the STL (though I'd like to get there someday) -- it's to teach you how to use the core language mechanics of C++, so that if you want to learn more about the STL (or anything else that builds upon the core mechanics), you'll be well set up for doing so!

  • Marius

    How do we pronounce the '#' symbol here?

  • Sharaf

    hey, do you mean
    if i have defined bob then if i use #ifndef it will not print it?

  • Stanley Delva

    Can you declare variables in a header file for later use?

    • Alex

      You can define variables in a header, though it might not work like you expect. What actually happens is that when you #include the header file in your .cpp file, all of the lines of the header get copied into the .cpp file. So if you've defined any variables in the header, they get copied into the .cpp and treated as if you'd defined them in the .cpp file. If the header is #included in multiple .cpp files, each gets their own copy of the variable (which may or may not cause naming conflicts).

      Defining variables in a header is usually undesirable. IMO, the only variables that you should define in a header are constants that you use in your program.

      It is okay to forward declare variables in a header if that makes sense for what you're doing (we talk about how to do this in chapter 4).

  • Kevin

    Hey! I made a small program just messing around, and during the last couple lessons I've been editing it to make it simpler/easier to read, here it is

    math.h contains

    Anyways, the problem I'm having is when I try to shove playerInput into its own file and put a function prototype, it doesn't give the inputs (x and y) to main(). It'll always give me 0 as the output. What am I doing wrong? Does playerInput just have to be within the same file as main()?

    • Alex

      playerInput() can be in a separate file, if you write it correctly. The problem is that you're using global variables to pass data between functions, which is a bad idea.

      There are ways to fix this so it will do what you want, but honestly, any solution in that regard is putting a band-aid on bad habits.

      You should get rid of x and y as global variables and utilize local variables, parameters, and return values to move the necessary values between the functions.

  • Essi

    Thanks for the quick response.

    I faced another error Error C2084: 'Function already has a body'. However, I fixed the problem.
    The issue is when building a project, it is always better to keep the project name the same as the cpp file that contains the main() function.
    Thanks again. :)

  • Essi

    Thanks for this nice tutorials.

    I'm using MS Visual Studio 2015, and I followed the codes in this page, but I get the two linking errors LNK1169:"one or more multiply defined symbols found" and also LNK2005: "_main already defined in main.obj".
    I googled the errors but I couldn't find the solution. Some suggest that this problem may occur when there is function definition in the header file?
    But this also does not work!! :(

    • Alex

      Sounds like you have function main() defined twice, possible in two different files in your project, or possible in a header file that's being included in multiple places.

      Make sure you have function main() defined in only one code (.cpp) file in your project.

  • BobZ

    Hi, Alex

    Avneet's question above was a good one.  But perhaps I am the only one on this planet who does not know what is an "object" in the C++ programming sense?  I had someone explain it to me a few years ago and I did not get it then, so I guess I need a very patient explanation.........  I did a quick search of the word in the previous few lessons and did not see where you define it anywhere?  I hope you do not object to my question.  :-)

    • Alex

      An object in C++ programming generally refers to a self-contained data structure that includes functions that operate on that data.

      But in the context of these macros, the word object has a different meaning. They're called object-like macros because the identifiers that are defined look like data objects (e.g. constant variables), as opposed to function-like macros, which look like function calls.

      Don't get too hung up on this, it's just a name. :)

  • elRaimundo

    Hi and first of all,
    thanks for the great tutorial!
    I have run into a problem trying to compile my project if I add the following preprocessor directives:

    I get the following error in eclipse cdt on the first call to std::cout (I hope I'm using the correct terminology here):
    error: no type named 'cout' in namespace 'std'
    <iostream> is clearly included and I get no complaints about std::cout when its used later in main,
    so what am I missing here?

    • Alex

      The problem here is that lines 5 and 9 are outside of a function, so your compiler is confused because you're declaring statements somewhere you aren't supposed to.

      Try copying lines 4 through 10 into your main() function (or another function that main() calls) and it should work fine.

  • Paras

    Hi Alex.Thanks for your wonderful lessons. I am very new to programming, I hope I am asking the right question. This is the code I was practising. Here system ("paused"); does not work for some reason. It just blinks and goes away but if I use
    cin.ignore(255, 'n');
    works fine.

    Would you please don't mind to explain? Sorry for the bad English too :-(

    • Alex

      The cin method clears out any queued input, then waits for the user to press a key before proceeding.

      The method of using system("pause") (no d on the end of pause) makes a call to the operating system to run the pause executable (if you open a command prompt on Windows, you can type "pause" (no quotes) and see it execute).

      I recommend the cin method because it will work on any operating system.

  • nice article....explained well...But there are 14 directives in C++
    You have written about few of them.What about others?

    • Alex

      It's an intro lesson, so I've opted not to be comprehensive here in the interest of having the lesson not be overly-long. I'll take a note that we could use a more comprehensive lesson on the preprocessor. In the meantime, there's plenty of reference material available on the internet that can explain these things. Once you understand how the preprocessor works and some of it's basic functions, picking up the other directives shouldn't be too much of an issue.

  • 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.

  • Learner

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

  • 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?

  • Anand


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

  • 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


    • Alex

      Your #define symbols can be whatever you like so long as they follow the normal identifier naming rules. There's no difference between #define PRINT_JOE and #define JOE and anything else. The word PRINT is meaningless in this context except maybe as a note to the reader.

  • 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?

  • 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?

  • arvind

    Great Article , Thanks Alex

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

  • 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


    • 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.

  • 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:

    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.

  • 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

    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?

    • Mayur B.

      I'm learning programming for small electronic projects which include micro-controllers, and to me object-like macros w/o substitution text are more frequent than the others.
      Here's an example.

      in above code, if I don't want to blow buzzer, then I just comment out the line

      There are may be million examples in every domain, but this is the best one I can think of.
      Thanks, Mayur

      • Mayur B.



  • 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.

  • 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 :)

Leave a Comment

Put all code inside code tags: [code]your code here[/code]