C 为什么要三次调用下面的函数

C 为什么要三次调用下面的函数,c,C,我曾尝试过调试,但没有成功,我不明白为什么第二个printf()调用增量()三次,而第一个调用两次 #include <stdio.h> #define MAX(a, b) ( (a) > (b) ? (a) : (b) ) int increment(){ static int i = 42; i += 5; printf("increment returns %d\n", i); // 47, 52, 57 return i; } in

我曾尝试过调试,但没有成功,我不明白为什么第二个printf()调用增量()三次,而第一个调用两次

#include <stdio.h>

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

int increment(){
    static int i = 42;
    i += 5;
    printf("increment returns %d\n", i); // 47, 52, 57
    return i;
}

int main( int argc, char ** argv ) {
    int x = 50;
    // parameters compute from right to left side
    printf("max of %d and %d is %d\n",
                x, //3rd: 50
                increment(), //2nd: 52
                MAX(x, increment()) //1st: 50,47 -> 50
                );

    printf("max of %d and %d is %d\n",
                x, //3rd: 50
                increment(), //2nd: 62
                MAX(x, increment()) //1st: 50,57 -> 57
                );
    return 0;
}

因为你这么说:

MAX(x, increment())
评估为

( (x) > (increment()) ? (x) : (increment()) )
如果条件未满足,则计算
之后的部分,从而再次调用函数。

因为宏:
MAX(x,increment())
展开为:

( (x) > (increment()) ? (x) : (increment()) )
类似地,宏的下一个调用将展开

变量
i
是静态的,因此初始初始化时使用
i=42
,其递增值在不同的函数调用中保持不变

下面是一个函数调用序列,显示了由
increment()
函数返回的
i

 increment();    i = 47, First call

   x      52       x     i       
( (50) > (52) ? (50) : (52) ) 
        Second        // ^ not called because condition is True 50 > 52
第二次:

    increment();   i = 57, Third call

     x      i       x      i         
  ( (50) > (62) ? (50) : (67) ) 
          Forth          Fifth   // called because condition is False  50 > 62
这个顺序是根据你的输出

重要注意事项:由于函数参数的求值顺序未定义,因此使用不同的编译器可能会有不同的输出

使用宏非常“危险”:各种奇怪的事情都可能发生。例如,在您的例子中,如果调用
MAX(f(),g())
将两次调用产生最大结果的函数,另一个函数只调用一次。由于您使用的是
MAX(x,f())
f
被调用两次,当且仅当它给出的结果大于
x

特别是,宏将按如下方式展开:

 ( (x) > (increment())? (x):(increment()) )

因此,如果条件(需要对
increment()
进行一次求值的测试),则执行
increment()
以产生结果。

这是因为宏将展开为
((x)>(increment())?(x):(increment())


但是,这不是唯一的问题,您的代码包含未定义的行为。。参数不会按指定的顺序进行计算。

这是宏中副作用的经典示例。您的
max
宏示例如下:

x > increment() ? x : increment()
一旦增量()的返回值大于
x
时,三元运算符将调用
increment()
两次,一次用于评估条件,一次用于评估错误部分(这是第二个
increment()

在这种情况下,最好使用max
max\u int
函数:

int max_int(int a, int b)
{
  return a > b ? a : b;
}
调用此函数而不是
MAX
将确保您的参数只计算一次。

((a)>(b)?(a):(b))

在这个语句中,如果b代表一个函数,如果(a>b)为true,则只调用一次,如果(a>b)为false,则调用两次:一个用于给出比较参数(b在“(a)>(b)”中),另一个用于返回整个语句的值(b在宏的后半部分)

在您的例子中,有一个额外的调用“b”(increment),用于在每个测试中提供第二个整数参数


总共是两次和三次。

如果将最大增量值放在不同的变量中,会发生什么情况?请注意,您的代码包含未定义的行为。请尝试修复它,因为它可能导致恶性错误。恐怕没有参数传入此变量program@StefanoFalasca嗯,我可能错了,瓦拉格人的评价和其他人不一样吗参数?varargs在哪里?@StefanoFalasca调用
printf()
maybe?@StefanoFalasca哈哈,没问题:)“宏的使用非常不推荐”据我所知不是这样。虽然可能会发生一些你应该注意的奇怪的事情,但它们被广泛用于各种各样的事情。
int max_int(int a, int b)
{
  return a > b ? a : b;
}