2012-10-25 10 views
7

可能重複Cコードを実行中に下記のコードのため
Parameter evaluation order before a function calling in C間違った出力

を私は、出力20及び76であることが期待代わりに75と21の出力として来ています。なぜそうなのか説明してください。

#include<stdio.h> 

    unsigned func(unsigned n) 
    { 

     unsigned int a =1 ;   
     static unsigned int b=2;   
     a+=b; b+=a;   
     { 

     unsigned int a=3;   
     a+=b; b+=a;   
     } 
     //printf("%d %d ",a,b); 
     return (n+a+b);   
    } 
    int main() 
    { 
     printf("%d %d\n",func(4),func(5)); 
     return 0; 
    } 
+0

私はそれを確認していないが、私は強く、これを疑う:http://stackoverflow.com/questions/376278/parameter-evaluation-order-before-a-function-calling-in-c – Mysticial

答えて

10

あなたはfunc(5)の前にfunc(4)が呼び出されることを期待していますが、あなたのコンパイラで起こります。関数パラメータの評価の順番は、C標準による不特定です。だから、コンパイラは、まず呼び出す関数を自由に選択します。したがって、異なる実行では、同じコンパイラでそのように起こる可能性はほとんどありませんが、関数呼び出しの順序は異なる場合があります。

+0

うわー。これにより、すべてのprintf形式の関数と、おそらく他の多くのものが移植不可能になります。 – SomeWittyUsername

+4

@icepackなぜそう思う?標準が特定の順序を要求せず、*未指定*の動作に依存するコードを書くつもりなら、あなたの*コード*は移植可能ではなく、* printf()*ではないことを意味します。 –

+0

これは、「機能副作用」と呼ばれるよく説明されたシナリオであり、ほとんどすべての言語で発生する可能性があり、避けるべきです。 http://stackoverflow.com/a/13063692/986760 – fayyazkl

1

引数は逆の順序でスタックにプッシュされます。あなたのコンパイラの実装では、func(4)の前にfunc(5)が呼び出されたようです。

3

FUNC(4)の評価の順序及びFUNC(5)C標準(S)によって定義されていません。

2

式の評価の順序はあなたがより多くの

Compilers and argument order of evaluation in C++

Parameter evaluation order before a function calling in C

のためにそれを訪問することを好むかもしれない unspecified behaviourあなたは

になって、したがってfunc(4)func(5)は異なる順序で呼ばれることもあります

+0

あなたは未指定を意味します。プログラムは不特定の動作を示しますが、私が知る限り、未定義の動作はしません。 (「関数指定子の評価の順序、実際の引数、実際の引数内の部分式は指定されていません」C99 6.5.2.2:10) –

+0

@Pascal:そうだね。実際には – Omkant

1

評価の順序が原因である可能性があります。なぜなら、

//printf("%d %d\n",func(4),func(5)); 
     printf("%d \n",func(4)); 
     printf("%d \n",func(5)); 

印刷(5)が最初に実行取得さ

20 
76 
0

FUNC:FUNC(5)を実行した後の変数の

値:

a = 3 
b = 13 
func(5) = 21 

をB、以来func(4)を実行した後の値:

a = 14 
b = 57 
func(4) = 75 
0

コードは単純で、static変数は関数呼び出しの間に値を保持することを忘れないでください。コンパイラによるプログラムで

、(これ規格で定義されていない、特定のコンパイラ):

func(5)が最初に実行され、21を返します。.. 説明:

unsigned func(unsigned n) /*first with 5*/ 
    { 

     unsigned int a =1 ;   
     static unsigned int b=2;   
     a+=b; b+=a;  // a = 3, b = 5 
     { 

     unsigned int a=3;   
     a+=b; b+=a;  // a = 8, b = 13 
     } 
     //printf("%d %d ",a,b); 
     return (n+a+b);  // 5 + 3 + 13 = 21. 
    } 

FUNC(4)次に実行される、

説明:

unsigned func(unsigned n) /*first with 5*/ 
    { 

     unsigned int a =1 ;   
     static unsigned int b=2;   
     a+=b; b+=a;  // a = 14, b = 27 
     { 

     unsigned int a=3;   
     a+=b; b+=a;  // a = 30, b = 57 
     } 
     //printf("%d %d ",a,b); 
     return (n+a+b);  // 4 + 57 + 14 = 75(which is printed first). 
    } 

したがって出力。

0

「機能副作用」と呼ばれるこれに関してよく知られている用語があります。関数内の変数を変更し、その関数を呼び出し、変数がすでに変更されていることを期待する変数を使用して文に頼ります。一般的には、これは避けるべきであり、良いアプローチではありません。

このようなシナリオでは、関数を呼び出して戻り値を格納し、printfで使用するか、2つの異なるprintf呼び出しを行う方が良いでしょう。

side effects

関連する問題