#include <stdio.h> int f(int, int, int) { return 0; } int main() { return f(printf("a"), printf("b"), printf("c")); }
这是今天晚上遇到的腾讯在线笔试题目,问题是 “代码结果是什么?”这道题目结果是 cba 吗?为什么?
业精于勤,荒于嬉;行成于思,毁于随。
テンセントがこの種の未定義の動作について問題を提起するだけで十分です。 「結果が cba かどうかは関係ありません。重要なことは、日常業務でそのようなコードを書かないことです。コードの 1 行にあまりにも多くの関数呼び出しを書かないようにしてください。チェーン呼び出し; 副作用のある関数呼び出しの場合は、複数行で記述する必要があります。
ほとんどの呼び出し規則はスタックを右から左にプッシュします。つまり、f(a, b, c) のように、最初に右端のパラメータがスタックにプッシュされ、次に c が最初にスタックにプッシュされ、次に b が続きます。 、そして最後に 。特に、最初にスタックにプッシュされるのは printf("c") の戻り値であるため、ここで printf("c") の呼び出しが行われます。したがって、このコードの関数呼び出し順序は最終的に printf("c")、printf("b")、printf("a")、f(1,1,1) となります。したがって、コードの結果は cba になります。
C 言語のデフォルトの呼び出し規約は cdecl で、これはスタックを右から左にプッシュすることを意味します。ただし、パラメーター リストの評価順序は未定義の動作であり、関数パラメーター リスト内のカンマはシーケンス ポイントではありません。 msvc と x86 gcc のデバッグ バージョンは右から左に評価されるようですが、私の知る限り、Sparc はその逆のようです。最適化されたリリース バージョンに関しては、さらに確実性が低くなります。
テストはパラメータをスタックにプッシュする方向に関するもので、答えは cba です。これについては上で詳しく説明しています。 私が言いたいのは、テンセントの筆記試験問題の前に、試験問題に関する秘密保持契約があることを覚えているということです。技術的な質問に対する答えを追求することは何も悪いことではありませんが、質問の所有者はその規定にも従わなければなりません。あなたが同意した契約。
パラメータを渡す順序は評価の順序と等しくありません。つまり、この質問は間違っているはずですが、呼び出し規約ではパラメータを右から右に渡すことがほとんどであるため、選択する場合は cba を選択することをお勧めします。左、質問者が誤解している可能性があります
しかし、main 関数は f 関数を返し、f 関数の戻り値は 0 ですが、なぜ main 関数の戻り値は 0 にならないのでしょうか?
テンセントがこの種の未定義の動作について問題を提起するだけで十分です。 「結果が cba かどうかは関係ありません。重要なことは、日常業務でそのようなコードを書かないことです。コードの 1 行にあまりにも多くの関数呼び出しを書かないようにしてください。チェーン呼び出し; 副作用のある関数呼び出しの場合は、複数行で記述する必要があります。
ほとんどの呼び出し規則はスタックを右から左にプッシュします。つまり、f(a, b, c) のように、最初に右端のパラメータがスタックにプッシュされ、次に c が最初にスタックにプッシュされ、次に b が続きます。 、そして最後に 。特に、最初にスタックにプッシュされるのは printf("c") の戻り値であるため、ここで printf("c") の呼び出しが行われます。したがって、このコードの関数呼び出し順序は最終的に printf("c")、printf("b")、printf("a")、f(1,1,1) となります。したがって、コードの結果は cba になります。
C 言語のデフォルトの呼び出し規約は cdecl で、これはスタックを右から左にプッシュすることを意味します。ただし、パラメーター リストの評価順序は未定義の動作であり、関数パラメーター リスト内のカンマはシーケンス ポイントではありません。 msvc と x86 gcc のデバッグ バージョンは右から左に評価されるようですが、私の知る限り、Sparc はその逆のようです。最適化されたリリース バージョンに関しては、さらに確実性が低くなります。
テストはパラメータをスタックにプッシュする方向に関するもので、答えは cba です。これについては上で詳しく説明しています。
私が言いたいのは、テンセントの筆記試験問題の前に、試験問題に関する秘密保持契約があることを覚えているということです。技術的な質問に対する答えを追求することは何も悪いことではありませんが、質問の所有者はその規定にも従わなければなりません。あなたが同意した契約。
パラメータを渡す順序は評価の順序と等しくありません。つまり、この質問は間違っているはずですが、呼び出し規約ではパラメータを右から右に渡すことがほとんどであるため、選択する場合は cba を選択することをお勧めします。左、質問者が誤解している可能性があります
の評価順序も同様です。しかし、main 関数は f 関数を返し、f 関数の戻り値は 0 ですが、なぜ main 関数の戻り値は 0 にならないのでしょうか?