宏中参数的意外多重评估

0 c macros

为什么第二个printf的输出是:最大50和67是62?为什么不是50和62的最大值是57?

#define MAX(a,b) ((a)>(b) ? (a): (b))
int incr(){
    static int i =42;
    i += 5;
    return i;
}
int _tmain(int argc, _TCHAR* argv[])
{   
    int x = 50;
    printf("max of %d and %d is %d\n",x, incr(), MAX(x, incr()));
    printf("max of %d and %d is %d",x, incr(), MAX(x, incr()));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Yu *_*Hao 5

printf("max of %d and %d is %d\n",x, incr(), MAX(x, incr()));
Run Code Online (Sandbox Code Playgroud)

宏替换后,它变为:

printf("max of %d and %d is %d\n",x, incr(), ((x)>(incr()) ? (x): (incr())));
//                                    ^1            ^2               ^3
Run Code Online (Sandbox Code Playgroud)

incr()在这个单个函数调用中被多次调用,未指定哪个参数首先被计算.无论第一个还是第二个被调用,都会使结果出乎意料.

唯一可以确定的是由于短路?:,(x)>(incr()被评估以确定表达式是否具有值的值(x)或第三个的值incr().

  • 为了挑剔,没有值传递给'MAX`.字符串`incr()`传递给`MAX`.它将它转换为`((x)>(incr())?(x):( incr()))`.这些行中有两个或三个`incr()`的评估,具体取决于哪个fork`?:`.但是,未定义的行为和所有这些.@erapert:不,函数调用不一定是从左到右评估的; 应该避免这种事情. (4认同)
  • @Amadan这里没有未定义的行为; 只是未指明 (3认同)