_cdeclと_stdcallの2つの関数呼び出し方式の違い

2301 ワード

1.各種の関数呼び出し方式を紹介する:
_cdeclはC Declarationの略で、C言語のデフォルトの関数呼び出し方法を表します.すべてのパラメータが右から左に順にスタックに入り、これらのパラメータは呼び出し者によって消去され、手動スタックと呼ばれます.呼び出された関数は、呼び出し元にどれだけのパラメータを渡すかを要求する必要はありません.呼び出し元が多すぎるか少なすぎるパラメータは、コンパイルフェーズのエラーさえ発生しません.
_stdcallはStandard Callの略で、Cの標準呼び出し方式です.すべてのパラメータが右から左に順にスタックに入り、クラスメンバーを呼び出す場合、最後にスタックに入るのはthisポインタです.これらのスタック内のパラメータは呼び出された関数によって返された後にクリアされ、使用される命令はretn Xであり、Xはパラメータが占有するバイト数を表し、CPUはret後にXバイトのスタック空間を自動的にポップアップする.自動清桟と呼ばれています.関数はコンパイル時にパラメータの個数を決定しなければならず、呼び出し者はパラメータの生成を厳格に制御しなければならず、多くてはならず、少なくてはならない.そうしないと、返された後にエラーが発生する.
PASCALはPascal言語の関数呼び出し方式であり、C/Cでも使用可能であり、パラメータスタック順は前者とは逆である.帰りの清桟方式は忘れました...
_fastcallはコンパイラが指定したクイックコール方式です.ほとんどの関数パラメータの個数が少ないため、スタック転送を使用するのに時間がかかります.だから_fastcallは、通常、最初の2つ(または複数)のパラメータをレジスタによって伝達するか、残りのパラメータをスタックによって伝達するかを規定する.コンパイラによってコンパイルされるプログラムによって規定されるレジスタが異なります.戻り方法と_stdcallは相当です.
_thiscallはクラスメンバー呼び出しでthisポインタが渡されるのを解決するために規定されています._thiscallは、コンパイラによって決定される特定のレジスタにthisポインタを置くことを要求します.VCはecx,BorlandのCコンパイラはeaxを用いる.戻り方法と_stdcallは相当です.
_fastcallと_thiscallに関連するレジスタはコンパイラによって決定されるため、コンパイラにまたがるインタフェースとして使用できません.したがって、Windows上のCOMオブジェクトインタフェースはすべて_stdcall呼び出し方式.
Cに説明なしのデフォルト関数は_cdecl方式(Cでもこの方式しか使用できません)、Cも同様ですが、デフォルトの呼び出し方式はIDE環境で設定できます.
可変パラメータを持つ関数は必須であり、使用可能である_cdecl方式、例えば次の関数です.
int printf(char * fmtStr, ...);
int scanf(char * fmtStr, ...);

2.windef.hにおける各種関数呼び出し方式のマクロ定義:
#define CALLBACK     __stdcall
#define WINAPI       __stdcall
#define WINAPIV      __cdecl
#define APIENTRY     WINAPI
#define APIPRIVATE   __stdcall
#define PASCAL       __stdcall
#define cdecl _cdecl
#ifndef CDECL
#define CDECL _cdecl
#endif

3.ヒント
:
ほとんど私たちが書いたWINDOWS API関数は__です.stdcallタイプですが、なぜですか??
両者の違いについて,(1)WINDOWSの関数呼び出しにはスタック(STACK,先入後出の記憶構造)が必要である.関数呼び出しが完了すると、スタックはクリアする必要があります.ここが問題の鍵です.どのようにクリアしますか?もし私たちの関数が使用されたら_cdeclでは、スタックの消去作業は呼び出し者によって行われ、COMの用語で言えば顧客によって行われる.これにより、異なるコンパイラがスタックを生成する方法が異なるという厄介な問題が発生し、呼び出し者は正常にパージ作業を完了することができますか?答えはできない.使用する場合stdcall、上の問題は解決して、関数は自分でクリアの仕事を解決します.したがって、プラットフォーム間での呼び出しでは、__を使用します.stdcall(WINAPIのように現れることもありますが).(2)ではなぜ_cdeclは?このような関数、例えばfprintf()に遭遇すると、そのパラメータは可変で、不定長であり、被呼び出し者は事前にパラメータの長さを知ることができず、事後のクリア作業も正常に行われないため、このような場合は_cdecl.ここでは、プログラムに可変パラメータが含まれていない場合は、__を使用したほうがいいという結論があります.stdcallキーワード