What is double evaluation and why should it be avoided?

前端 未结 4 1865
情歌与酒
情歌与酒 2020-12-09 01:27

I was reading that in C++ using macros like

#define max(a,b) (a > b ? a : b)

can result in a \'double evaluation\'. Can someone give me

4条回答
  •  一整个雨季
    2020-12-09 01:44

    The macro language in C and C++ is processed by a dedicated parser at the 'pre-processing' stage; the tokens are translated and the output is then fed into the input stream of the parser proper. #define and #include tokens are not recognized by the C or C++ parsers themselves.

    This is important because it means that when a macro is said to be "expanded" it means literally that. Given

    #define MAX(A, B) (A > B ? A : B)
    
    int i = 1, j = 2;
    MAX(i, j);
    

    what the C++ parser sees is

    (i > j ? i : j);
    

    However if we use the macro with something more complex, the same expansion happens:

    MAX(i++, ++j);
    

    is expanded to

    (i++ > ++j ? i++ : ++j);
    

    If we pass something that makes a function call:

    MAX(f(), g());
    

    this will expand to

    (f() > g() ? f() : g());
    

    If the compiler/optimizer can demonstrate that f() has no side-effects, then it will treat this as

    auto fret = f();
    auto gret = g();
    (fret > gret) ? fret : gret;
    

    If it can't, then it will have to call f() and g() twice, for example:

    #include 
    
    int f() { std::cout << "f()\n"; return 1; }
    int g() { std::cout << "g()\n"; return 2; }
    
    #define MAX(A, B) (A > B ? A : B)
    
    int main() {
        MAX(f(), g());
    }
    

    Live demo: http://ideone.com/3JBAmF

    Similarly if we were calling an extern function, the optimizer may not be able to avoid calling the function twice.

提交回复
热议问题