1

誰でも、以下のコードの出力を理解するのを手伝ってもらえますか:

int main()
{
    int a=35;
    printf("%d %d %d %d %d",a--,a,a=20,a++,a=39);
    return 0;
}

出力:20 19 19 39 19

printf関数のcで割り当てがどのように処理(コンパイル)されるかについての洞察を高く評価しました。

4

2 に答える 2

7

これは不特定の動作です。関数の引数の評価順序は C 標準では指定されていないため、任意の順序で発生する可能性があります。

人々は、あなたが読むことができるコメントですでにあなたにいくつかのリンクを与えています. しかし、要するに「シーケンスポイント」と呼ばれるものがあります。これらにより、以前に実行する必要があったすべてが実行され、その後プログラムを続行できることが保証されます。2 つのシーケンス ポイント間では、命令は任意の順序で実行できます。

C11標準から:

3.4.4:


  1. 規定の動作 未規定の値の使用、またはこの国際規格が 2 つ以上の可能性を提供し、いずれの場合もどちらが選択されるかについてそれ以上の要件を課さないその他の動作

  2. 規定されていない動作の例は、関数への引数が評価される順序です。

6.5.2.2.10 言う

関数指定子と実際の引数の評価の後、実際の呼び出しの前に、シーケンス ポイントがあります。呼び出された関数の本体の実行の前後に特に順序付けされていない呼び出し側関数 (他の関数呼び出しを含む) 内のすべての評価は、呼び出された関数の実行に関して不定に順序付けられます。

つまり、関数の引数の評価の間にシーケンス ポイントがないため、コンパイラが好む順序で評価することができます。

a答えを完成させるために、2 つのシーケンス ポイント間で値を複数回変更しようとするため、これも未定義の動作です。

6.5.2:

スカラー オブジェクトに対する副作用が、同じスカラー オブジェクトに対する別の副作用または同じスカラー オブジェクトの値を使用した値の計算と比較してシーケンス化されていない場合、動作は未定義です。式の部分式に複数の許容される順序付けがある場合、順序付けのいずれかでそのような順序付けされていない副作用が発生した場合、動作は未定義です。84)

84)
i = ++i + 1;
a[i++] = i;
彼のパラグラフは、 while allowのような未定義のステートメント式をレンダリングします。
i = i + 1;
a[i] = i;

于 2012-07-31T09:06:23.067 に答える
0
printf("%d %d %d %d %d",a--,a,a=20,a++,a=39);

これは未定義の動作です。

これは、プログラムが印刷できることを意味します:20 19 19 39 19または0 0 0 0 0、ハード ドライブをフォーマットすることさえできます。

(C99, 6.5p2) 「オブジェクトは、前のシーケンス ポイントと次のシーケンス ポイントの間で、式の評価によって最大 1 回変更された格納値を持つものとします。

もちろん、制約ではない「shall」の違反は、プログラムが未定義の動作を呼び出すことを意味します (C99 の 4.p2 を参照)。

于 2012-07-31T09:31:35.397 に答える