main()
{
int i=5;
printf("%d%d%d%d%d%d",i++,i--,++i,--i,i);
}
出力は45545ですが、どのように機能しているかわかりません。関数呼び出しの引数は、左から右にスタックにプッシュされると言う人もいます。
関数パラメータの評価順序は指定されていません。
c99標準から:
6.5.2.2関数呼び出し
10 /関数指定子、実際の引数、および実際の引数内の部分式の評価の順序は指定されていませんが、実際の呼び出しの前にシーケンスポイントがあります。
ただし、これは問題の一部にすぎません。もう1つのこと(未定義の動作が含まれるため、実際にはさらに悪いことです)は次のとおりです。
6.5式
2 /前のシーケンスポイントと次のシーケンスポイントの間で、オブジェクトは、式の評価によって、格納されている値を最大で1回変更する必要があります。さらに、前の値は、格納される値を決定するためにのみ読み取られるものとします。
;
この場合、すべての引数の評価は、関数が入力される前のポイントと、すべての引数が評価された後のポイントの2つのシーケンスポイントの間でのみ行われます。このようなコードは書かない方がいいでしょう。
C標準は、コンパイラーが行う可能性のある最適化の余地を残すために、いくつかの場所でかなり緩和されています。
関数にパラメーターが渡される順序は、標準では定義されておらず、コンパイラーが使用する呼び出し規約によって決定されます。あなたの場合、関数の引数が右から左に評価されるcdecl呼び出し規約(多くのCコンパイラがx86アーキテクチャに使用する)が使用されていると思います。
2つのポイント:
i
シーケンスポイントの前に複数回変更することは許可されていません。この関数呼び出しは未定義の動作です。
printf("%d%d%d%d%d%d",i++,i--,++i,--i,i);
2つのシーケンスポイント間でオブジェクトを複数回変更することは、Cでは未定義の動作です。
また、変換仕様は6つありますが、フォーマットの引数は5つしかないため、これは未定義の動作です。
printf
引数の評価順序は指定されていません。これは、とりわけ、使用しているシステムの呼び出し規約によって異なります。i
さらに、シーケンスポイントなしで数回変更しているため、これも未定義の動作です。ところで、欠落している議論があります。