3

私はデバッグしようとしましたが、2番目のprintf()がincrement()を3回呼び出すのに、最初のものは予想どおり2回呼び出す理由を理解できません。

#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;
}

結果

increment returns 47
increment returns 52
max of 50 and 52 is 50
increment returns 57
increment returns 62
increment returns 67
max of 50 and 67 is 62
4

6 に答える 6

10

あなたがそう言うからです:

MAX(x, increment())

に評価されます

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

条件が満たされない場合、 の後の部分:が評価され、関数が再度呼び出されます。

于 2013-07-29T07:59:04.707 に答える
4

macro:は次MAX(x, increment())のように展開されるため:

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

同様に、マクロの次の呼び出しが展開されます。

変数iは静的であるため、最初は で初期化されi = 42、インクリメントされた値はさまざまな関数呼び出しで保持されます。

i関数によって返される値とともに示される一連の関数呼び出しの下increment()

 increment();    i = 47, First call

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

2回目:

    increment();   i = 57, Third call

     x      i       x      i         
  ( (50) > (62) ? (50) : (67) ) 
          Forth          Fifth   // called because condition is False  50 > 62

このシーケンスは、出力によるものです。

関数の引数の評価順序は定義されておらず、未定義の動作であるため、コンパイラが異なると出力が異なる場合があることに注意してください

http://www.stroustrup.com/bs_faq2.html#マクロ

于 2013-07-29T07:59:41.817 に答える
1

これは、マクロが として展開されるために発生します( (x) > (increment()) ? (x) : (increment()) )

ただし、これが唯一の問題ではありません。コードに未定義の動作が含まれています。パラメータは、指定された順序で評価されません。

于 2013-07-29T08:01:27.113 に答える
1

これは、マクロの副作用の典型的な例です。マクロmaxの例は次のとおりです。

x > increment() ? x : increment()

xincrement() からの戻り値が 3 項演算子よりも大きい場合はincrement()、条件を評価するために 1 回、偽の部分 (2 番目のincrement()) を評価するために 1 回、2 回呼び出します。

この場合、最高の最善の方法は、 max_int機能を最大化することです。

int max_int(int a, int b)
{
  return a > b ? a : b;
}

代わりにこれを呼び出すMAXと、引数が一度だけ評価されるようになります。

于 2013-07-29T08:02:04.237 に答える
0

マクロの使用は非常に「危険」です。あらゆる種類の奇妙なことが起こる可能性があります。たとえば、あなたの場合、MAX( f(), g() )最大の結果をもたらす関数を呼び出すと、2 回呼び出され、もう 1 つの関数は 1 回だけ呼び出されます。を使用しているため、 より大きい結果が得られた場合にのみMAX(x, f())、が 2 回呼び出されます。fx

特に、マクロは次のように展開されます。

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

結果を生成するために条件 ( の 1 回の評価を必要とするテストincrement())increment()が実行される場合。

于 2013-07-29T08:01:23.470 に答える
0

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

In this statement, if b stands for a function, it will be called just once if (a > b) is true, but twice if (a > b) is false: one to give parameters for the comparison(b in "(a) > (b)"), the other to return a value for the whole statement(b in the latter part of the macro).

In your case, there's an extra call of "b"(increment) to provide the second integer parameter in each test.

Altogether, its twice and thrice.

于 2013-07-29T08:06:16.073 に答える