C言語関係掲示板

過去ログ

No.67. 引数の評価順序


実行結果に疑問がでたので、教えてください。
#include <iostream.h>

int func()
{
    static int a = 10;
    return a++;
}
int main(void)
{
    cout << func() << endl
         << func() << endl;
    return 0;
}

とすると、実行結果は
11
10
となります。また、
#include <iostream.h>

int func()
{
    static int a = 10;
    return a++;
}
int main(void)
{
    cout << func() << endl;
    cout << func() << endl;
    return 0;
}

とすると、実行結果は
10
11
となりました。この2つの違いは何から生じているものなのでしょうか?
というのも、
#include <iostream.h>

int main(void)
{
    cout << "x" << endl
         << "y" << endl;
    
    cout << "x" << endl;
    cout << "y" << endl;
    return 0;
}

の実行結果は
x
y
x
y
となるからです。どのように理解すればよいのでしょうか?
宜しくお願いします。


こんにちは、ともじです。

staticについては、OKですね。
http://www9.plala.or.jp/sgwr-t/sec12.htm#s12-2

で、関数の引数の評価順序なんですが、
「Cプログラミングの非常識」河西朝雄著 技術評論社によると、

  MS-DOS系の多くのC処理系では、引数は後(右)から評価し、すべてを評価し
  終わるまで次の引数の評価に進まない(インターリーブしない)。
   このため、

   static int a[] = {10,20,30};
   int *p=a;

   printf("%d %d\n",*p++,*p++);
              (1) (2)

   は、(2)、(1)の順に評価されるので、予想に反して、

   20 10

   と出力されることになる。

ということで、C++ で coutを使った出力でも、同様の結果になるということなんですね。

実は私も知らなかったので、勉強になりました。 
#以前読んで気になったんでしょうね。このページ、付箋が貼ってありました。
#でも、すっかり忘れていました。今度は忘れないぞ。


うろオーボエ【ブオー】なので……。ちゃんと調査。

 関数の引数が大抵スタックみたいに実装されているため、後から評価さ
れる、というのを聞いたことがあります。
 私も気になったので BCB のデバックモードで殆ど知らないニーモニック
とにらめっこしてみましたよ。で、みたところ、確かに右から引数を評価
して関数に渡しておりました。
 私が試したのは、
int a = 0;
cout << a++ << ++a << endl;

 というコードですが、これのアセンブリの一部は、次の通り。
push 0x00401194                 // 関数 endl のアドレスを stack にpush
inc dword ptr [ebp-0x04]        // edx をインクリメント
mov edx,[ebp-0x04]              // a を edx レジスタへ
push edx                        // edx を stack に push
mov ecx,[ebp-0x04]              // a を ecx へ
inc dword ptr [ebp-0x04]        // a をインクリメント
push ecx                        // ecx をプッシュ
push dword ptr [CC3250.std::cout] // オブジェクト cout をプッシュ
// 以下関数呼び出し作業につき略。引数は pop して得ている。


とまあ、確かに右からで stack で実装されていました。はい。私も勉強になりました。

 暇があったらアセンブリコードを見てみると為になります。
 私は、今為になりました。良かった良かった【謎】


inc dword ptr [ebp-0x04]        // edx をインクリメント

 ですが、edx じゃなくて、a です。はい。失礼しました。


有難う御座いました。
また質問する際には、宜しくお願いします。

戻る


「初心者のためのポイント学習C言語」 Last modified:2001.11.15
Copyright(c) 2000-2002 TOMOJI All Rights Reserved