10

私はいくつかのCコードを持っています:

main()
{
    int a=1;
    void xyz(int,int);

    xyz(++a,a++);     //which Unary Operator is executed first, ++a or a++?

    printf("%d",a);
}
void xyz(int x,int y)
{
    printf("\n%d %d",x,y);
}

この関数xyzには と の 2 つのパラメーターが渡され++aますa++。誰かが結果を説明するための一連の操作を説明できますか?

上記のコードは、使用されているコンパイラに応じて「3 13」または「2 23」を出力します。

4

4 に答える 4

28

さて、サンプル コードで考慮すべき点が 2 つあります。

  1. 関数の引数の評価順序は規定されていないため、 または が最初に評価されるかどう++aa++は実装依存です。
  2. 変更の間にシーケンス ポイントを指定せずに の値をa複数回変更すると、未定義の動作が発生します。したがって、コードの結果は未定義です。

コードを単純化し、未指定および未定義の動作を削除すると、次の質問に答えることができます。

void xyz(int x) { }

int a = 1;
xyz(a++); // 1 is passed to xyz, then a is incremented to be 2

int a = 1;
xyz(++a); // a is incremented to be 2, then that 2 is passed to xyz
于 2010-06-07T13:12:23.853 に答える
9

Kernighan & Ritchie の第 2.12 章を引用します。

関数の引数が評価される順序は指定されていないため、ステートメント

printf("%d %d\n", ++n, power(2, n)); /* WRONG */

power が呼び出される前に n がインクリメントされるかどうかに応じて、異なるコンパイラで異なる結果を生成できます。解決策は、もちろん、書くことです

++n;
printf("%d %d\n", n, power(2, n));

関数呼び出し、入れ子になった割り当てステートメント、インクリメント演算子とデクリメント演算子は、「副作用」を引き起こします。式の評価の副産物として、変数が変更されます。副作用を伴う式では、式に含まれる変数が更新される順序に微妙な依存関係が生じる可能性があります。1 つの不幸な状況は、次のステートメントに代表されます。

a[i] = i++;

問題は、添字が i の古い値なのか新しい値なのかということです。コンパイラはこれをさまざまな方法で解釈し、その解釈に応じてさまざまな回答を生成できます。この規格では、意図的にそのような事項のほとんどを未指定のままにしています。副作用 (変数への割り当て) が式内で発生する場合は、最適な順序がマシンのアーキテクチャに大きく依存するため、コンパイラの裁量に任されています。(標準では、関数が呼び出される前に引数に対するすべての副作用が有効になることを指定していますが、上記の printf の呼び出しでは役に立ちません。) 道徳的には、評価の順序に依存するコードを記述することは、プログラミングでは悪い習慣です。どんな言語でも。当然、何を避けるべきかを知る必要がありますが、そうしないと

于 2010-06-07T13:20:22.393 に答える
1

関数の単項演算子評価シーケンス:

#include <stdio.h>

void xyz(int x, int y) {
    printf("x:%d y:%d ", x, y);
}

main() {
    int a;
    a=1;    xyz(++a, a);        printf("a:%d\n", a);
    a=1;    xyz(a, a++);        printf("a:%d\n", a);
    a=1;    xyz(++a, a++);      printf("a:%d\n", a);
}

出力します

x:2 y:2 a:2
x:2 y:1 a:2
x:3 y:1 a:3

私のシステムでは。これは、関数の 2 番目のパラメーターが最初に評価されることを示します。関数パラメータの評価順序に依存しないでください。定義されていないため、システムによって異なります。

ただし、この動作の気の利いた例を見つけるのは良い仕事です。

于 2010-06-07T13:21:32.270 に答える