見出し画像

【C言語】clang と VS と Eclipse と私(まだまだ続く 関数の評価順序)

C言語の関数の評価順序について。

こちらの記事の続きです。

しつこいわ、私って(笑)。

前記事で次のように申しました。

VS、gcc は本当に第3引数から評価しているのか

そして。

(1)引数の並びを逆にするとどうなるのか
(2)引数で関数を呼び出すとどうなるのか

この(1)(2)を試してみました。


(1)引数の並びを逆にするとどうなるのか

ソースコード

oe1、oe2、oe3、oe4 の各関数について少し解説します。
oe は 「Order Evaluation(評価の順序)」の略称です。
1~4 の4種類を用意しました。
それぞれ次のように引数を変えています。

一番のポイントはマクロ「MAX」の位置。
第1引数に置くのか、第3引数に置くのか。
引数を第1引数から評価するのか、第3引数から評価するのかを知ることが目的です。
oe3、oe4 は、更に i と j を単体で演算しました。
これによって評価の順序が変われば、演算結果が変わります。

以下がそのソースコードです。

#include <stdio.h>

#define MAX(x,y) ((x) > (y) ? (x) : (y))

void oe1(void)
{
    int i = 3;
    int j = 5;
    printf("MAX処理中 i = %d, j = %d, max = %d\n", i, j, MAX(++i,j--));
}

void oe2(void)
{
    int i = 3;
    int j = 5;
    printf("MAX処理中 max = %d, i = %d, j = %d\n", MAX(++i, j--), i, j);
}

void oe3(void)
{
    int i = 3;
    int j = 5;
    printf("MAX処理中 i = %d, j = %d, max = %d\n", i*=2, j--, MAX(++i,j--));
}

void oe4(void)
{
    int i = 3;
    int j = 5;
    printf("MAX処理中 max = %d, i = %d, j = %d\n", MAX(++i, j--), i*=2, j--);
}

int main()
{
    oe1();
    oe2();
    oe3();
    oe4();
    return 0;
}

結果

さて。
結果はどうなるでしょうか。

clang
MAX処理中 i = 3, j = 5, max = 4
MAX処理中 max = 4, i = 4, j = 3
MAX処理中 i = 6, j = 5, max = 8
MAX処理中 max = 4, i = 8, j = 3

VS2019
MAX処理中 i = 4, j = 3, max = 4
MAX処理中 max = 4, i = 4, j = 3
MAX処理中 i = 8, j = 3, max = 4
MAX処理中 max = 4, i = 8, j = 3

Eclipse
MAX処理中 i = 4, j = 3, max = 4
MAX処理中 max = 4, i = 4, j = 3
MAX処理中 i = 8, j = 3, max = 4
MAX処理中 max = 8, i = 8, j = 5

ん。
ん、ん、ん?
oe3 と oe4。
すごいことになってる。

まさかまさかの結果。
全体を見ると三者三様の有り様。

アセンブラはあるけど。

あー。
またほじくり返す?😅


(2)引数で関数を呼び出すとどうなるのか

ソースコード

評価順序を知る最も単純にしてわかりやすい方法は、関数を呼び出してみることです。呼び出された関数で標準出力に出力すれば一目瞭然。

ではやってみます。

ソースコードはこちら。

#include <stdio.h>

int func1(void)
{
    printf("func1\n");
    return 1;
}

int func2(void)
{
    printf("func2\n");
    return 2;
}

int func3(void)
{
    printf("func3\n");
    return 3;
}

int main()
{
    printf("func1 = %d, func2 = %d, func3 = %d\n", func1(), func2(), func3());
    return 0;
}

結果

上のソースコードを clang、VS、Eclipse のそれぞれの環境でコンパイルし実行してみます。

結果は次の通り。

clang
func1
func2
func3
func1 = 1, func2 = 2, func3 = 3

VS2019
func3
func2
func1
func1 = 1, func2 = 2, func3 = 3

Eclipse
func3
func2
func1
func1 = 1, func2 = 2, func3 = 3

VS2019 と Eclipse は右からなのかぁ。


後書き

さて。
例の (1) の結果。

どうなってるんでしょうねぇ。
アセンブラを解析するかなぁ。

この記事が気に入ったらサポートをしてみませんか?