19

私はCが初めてで、理解できないことが1つあります。関数がレジスタよりも大きくないものを返す場合、私のコンパイラはそれを EAX に入れます。大きな構造体 (ポインターではなく構造体自体) を返すと、スタック経由で返されます。

私の質問は、別のオブジェクトによってエクスポートされた関数を呼び出す方法をコンパイラがどのように知っているかです。呼び出し規約 (stdcall など) がありますが、それは戻り値を読み取るのではなく、引数を渡すことに関するものですよね?

「戻り値がEAXよりも大きいと宣言されている場合は、[bp-...]から取得する」などのルールが必要です。

もう 1 つ: 私が返したいオブジェクトは、レジスターよりも大きく、ヒープに格納し、スタック操作以外のすべてを防ぐためにポインターによって返す必要があると言うのは正しいでしょうか?

ありがとう。

4

2 に答える 2

19

戻り値が呼び出し元に渡される方法も、関数呼び出し規則の一部です。ここを参照してください。

例えば、以下についてcdecl

cdecl呼び出し規約は、x86 アーキテクチャの多くの C システムで使用されています。ではcdecl、関数パラメータは右から左の順序でスタックにプッシュされます。関数の戻り値は EAX レジスタに返されます (x87 レジスタ ST0 に返される浮動小数点値を除く)。

[...]

cdeclの解釈、特に値を返す方法にはいくつかのバリエーションがあります。その結果、異なるオペレーティング システム プラットフォーム用にコンパイルされた x86 プログラムや、異なるコンパイラによってコンパイルされた x86 プログラムは、両方がcdecl慣習であり、基盤となる環境を呼び出さないでください。一部のコンパイラは、EAX:EDX で 2 レジスタ以下の長さの単純なデータ構造を返します。また、例外ハンドラ (定義済みのコンストラクタ、デストラクタ、または代入など) による特別な処理を必要とするより大きな構造とクラス オブジェクトは、メモリに返されます。「メモリ内」で渡すには、呼び出し元がメモリを割り当て、そのメモリへのポインタを非表示の最初のパラメータとして渡します。呼び出し先はメモリにデータを入力してポインターを返し、戻るときに非表示のポインターをポップします。

ヒープにメモリを割り当てる場合、スタック操作は必要なヒープ操作よりもはるかに高速になるため、スタックは常に高速です。(C で) ヒープ上の何かへのポインターを返したい唯一の理由は、それがスタックに収まらないからです。

説明:

上記の最後の文で、「あなたが望むかもしれない唯一の理由...」は、「通常、ポインターを返す理由はない」と解釈されるべきではありません。むしろ、「ポインターを返さずに必要なことを実行できる場合、とにかくポインターを使用することを決定する唯一の理由は...」ということです。

もちろん、クリスが彼自身の答えで述べているように、関数からポインターを返す正当な理由はたくさんありますが、そうする必要がない場合についてのみ話しています。

つまり、可能な場合は値で返します。必要な場合はポインタを使用してください

于 2011-03-20T01:22:49.430 に答える
4

もう 1 つ: 私が返したいオブジェクトは、レジスターよりも大きく、ヒープに格納し、スタック操作以外のすべてを防ぐためにポインターによって返す必要があると言うのは正しいでしょうか?

まあ、多分。正直なところ、「ポインターによる戻り」または「値による戻り」の選択は、おそらく「戻りを速くしたい」よりも適切な理由があるはずです。たとえば、大きなオブジェクトの場合、スタック経由よりもポインター経由で戻る方が高速ですが、これは、スタックと比較してヒープにオブジェクトを割り当てるのにかかる時間が考慮されていません。

さらに重要なことに、ポインタによるリターンでは、不透明なポインタ、可変サイズのオブジェクト、およびスタック オブジェクトでは不可能なある程度のポリモーフィックな動作を使用できます。これらの種類の動作が必要な場合は、とにかく return-by-pointer を使用する必要があります。そうでない場合は、値による戻り値を使用するか、ユーザーが割り当てたオブジェクトへのポインターをパラメーターとして渡し (好みに応じて)、関数でそのパラメーターを変更します (これは " out パラメータ」など)。

どちらが速いと思うかではなく、必要なものとコードの動作に基づいて return メソッドを選択してください。絶対に速度が必要であることがわかった場合 (プロファイリングを行い、リターンがボトルネックであることを発見した後)、この種のマイクロ最適化について心配してください。

于 2011-03-20T01:32:06.587 に答える