Preprocessor Question

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • emaghero
    New Member
    • Oct 2006
    • 85

    Preprocessor Question

    Greetings one and all,

    I have a query about the preprocessor directive.

    I am coding in C++ in the MS Visual Studio environment.

    I was updating an old code recently where I had defined PI using the #define directive.

    Code:
    #define PI 3.1415926535897932385
    I decided to change this to

    Code:
    #define PI 4.0*atan(1.0)
    And the code ceased to work correctly. I think what is happening is that when I divide by PI it is dividing by 4.0 and multiplying atan(1.0).

    I didn't think this was supposed to happen with #define.

    What is the reason for this?

    Does the compiler call PI or does it replace PI with 4.0*atan(1.0) when it is seen?

    Is this a compiler dependent problem?
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    As you correctly titled this thread #define is a preprocessor directive. The preprocessor is NOT the compiler and only deals with preprocessor commands. The compiler can not handle preprocessor commands, they are not a part of the real language syntax.

    When a #define is used the preprocessor does a text substitution of the symbol name with the text text it is defined to so for your #define the code
    double oneoverpi = 1 / PI;

    is converted by the preprocessor to
    double oneoverpi = 1.0 / 4.0*atan(1.0);

    The compiler then compiles this using the normal operator precedence rules so effectively it does calculate (1.0 / 4.0)*atan(1.0).

    This is a known gotcha with #defines, you should always surround your #define with parenthesis which avoids the problem
    Code:
    # #define PI (4.0*atan(1.0))
    
    double oneoverpi = 1 / PI;
    
    // after preprocessing
    
    double oneoverpi = 1 / (4.0*atan(1.0));  // Calculation is correct
    No "calling" is done it is entirely text substitution.

    One final thought is that in C++ certainly it would be considered best practice not to use a #define for this at all but to use constant which then has the added benefit of proper type checking.
    Code:
    static const double PI = 4.0*atan(1.0);

    Comment

    • donbock
      Recognized Expert Top Contributor
      • Mar 2008
      • 2427

      #3
      Another issue to consider is that a #define macro that expands to a function call can't be used in file-scope initializers.

      Another issue to consider is performance. The atan() function will be called every time execution passes through a statement that refers to PI, including each pass through a loop.

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        Another issue is that macros that expand into a function stall the debugger since the code is not in the implementation but only the macro.

        Another issue is that there is no control on how the macro is applied. This means it can be expanded into code that won't compile or that produces indeterminate results.

        etc..etc...

        There are several C++ features specifically designed to replace macros:
        1) templates
        2) inline functions
        3) namespaces
        4) enums

        Use these in C++ rather than macos.

        Comment

        • emaghero
          New Member
          • Oct 2006
          • 85

          #5
          Thanks very much for all your help.

          Comment

          Working...