2

率直に申し上げると、これは指導が必要な宿題に関連しています。コードなどは必要ありませんが、これは私を夢中にさせているので、明確にする必要があります。私は本の中で質問さえしていません。

次のコードがあります。

int fun(int *c){
*c += 10;
return *c ;
}

void main(){

int a, b;
a = 10;
b = a + fun(&a);
printf("value of a is %d\n", a);
printf("With the function call on the right, ");
printf(" b is: %d\n", b);
a = 10;
b = fun(&a) + a;
printf("With the function call on the left, ");
printf(" b is: %d\n", b);
}

実行すると、「aの値は20」、「右側の関数呼び出しで40」、「左側の関数呼び出しで40」が得られます。

私が混乱しているのは、直前に非常によく似た質問があったことです

#include<stdio.h>

int fun(int *k) {
*k += 4;
return 3 * (*k) - 1;
}

void main() {
int i = 10, j = 10, sum1, sum2;
sum1 = (i / 2) + fun(&i);
sum2 = fun(&j) + (j / 2);

printf("%d", sum1);
}

そして、答えは sum1 の場合は 46、sum2 の場合は 48 になります。これは、私の頭では、codepad.org のコンパイラで左から右への評価で意味があります。しかし、Pelles C コンパイラでは 48 になります。最初の問題のコードがほとんど同じように配置されていることがわかります。

私はこのリンクを見つけました:この矛盾を説明しているように見えるCで呼び出す関数の前のパラメーター評価順序ですが、私の考え方から外れていないことを確認したいと思います。それで、それはコンパイラーに依存し、コンパイラーが最も効率的であると感じるものに依存していると言っても過言ではありませんか?

4

1 に答える 1

2

この両方の表現で

sum1 = (i / 2) + fun(&i);
sum2 = fun(&j) + (j / 2);

の部分式の評価の順序が指定されていないため、動作が指定されていません+。コンパイラは、呼び出しの前または(i/2)後に自由に評価できます。(j/2)

右辺の前に左辺の評価を強制する&&and演算子とは異なり、 、、、、およびすべてのビット演算子は、最適化戦略に応じて、コンパイラが最も便利な評価順序を選択できるようにします。これは、さまざまなコンパイラが異なる側面を評価することを決定する可能性があることを意味します。||+-*/%+

これが実際的な観点から何を意味するかというと、副作用のある式は同じ式で 1 ​​回しか使用しないということです。両方の式を書き直して、必要な評価順序を強制することができます。たとえば、

sum1 = i/2;
sum1 += fun(&i);

また

sum2 = sun(&j);
sum2 += j/2;
于 2014-11-25T04:18:23.123 に答える