Strange behaviour of macros C/C++

前端 未结 5 597
再見小時候
再見小時候 2020-12-04 03:02

I\'m using some macros, and observing some strange behaviour.

I\'ve defined PI as a constant, and then used it in macros to convert degrees to radians and radians to

相关标签:
5条回答
  • 2020-12-04 03:19

    First, cmath defines M_PI, use that.

    Second, cpp macros do textual substitution. Which mean that this:

    #define PI atan(1) * 4
    a = 1 / PI;
    

    will be turned into this:

    a = 1 / atan(1) * 4;
    

    before the c/c++ compiler gets a chance to see your code, and it will treat it equivalent to this:

    a = (1 / atan(1)) * 4;
    

    which is not what you want.

    Your define should look like this:

    #define PI (atan(1) * 4)
    

    and everything should be fine.

    This is not really strange behaviour, but well documented behaviour of the c-preprocessor.

    You should search the web for other pitfalls with macros. (hint: parameter passing)

    0 讨论(0)
  • 2020-12-04 03:20

    You should use parenthesis for your macros to specify precedence. In addition to that, i think in many cases math.h will define PI for you

    0 讨论(0)
  • 2020-12-04 03:23

    Also good practice: Add brackets around all your parameters:

    #define radians(deg)  ((deg) * PI / 180)
    

    because the expression you pass as parameter might include operators, too.

    Or even better: Use (inline-) functions instead of macros, to avoid surprises with sideeffects when a parameter is evaluated multiple times like here:

    #define sqr(x)  ((x) * (x))
    

    The only disadvantage you get with inline functions: You can define them for one type, only (unless you use C++ templates)

    0 讨论(0)
  • 2020-12-04 03:24

    Macros just do text substitution without regard for context, so what you wind up with is:

    cout << "PI, in degrees: " << atan(1) * 4 * 180 / atan(1) * 4 << endl;
    

    Note the distinct lack of parens around the second atan(1) * 4, causing it to divide only by atan(1) and then multiply by 4.

    Instead, use inline functions and globals:

    const double PI = atan(1) * 4;
    double radians(double deg) { return deg * PI / 180; }
    double degrees(double rad) { return rad * 180 / PI; }
    
    0 讨论(0)
  • 2020-12-04 03:32

    Macros are (relatively simple) textual substitutions.

    Use parentheses in your definitions (both to enclose the macro itself and the macro arguments):

    #define PI (atan(1) * 4)
    #define radians(deg)  ((deg) * PI / 180)
    #define degrees(rad)  ((rad) * 180 / PI)
    
    0 讨论(0)
提交回复
热议问题