重複の可能性:
C では、プログラムの実行は常にメインから開始されますか?
2 つの関数 (main を除く) を含むプログラムの実行を開始したい
void check(void)
void execute(void)
check() から実行を開始したいのですが、c/c++ で可能ですか?
重複の可能性:
C では、プログラムの実行は常にメインから開始されますか?
2 つの関数 (main を除く) を含むプログラムの実行を開始したい
void check(void)
void execute(void)
check() から実行を開始したいのですが、c/c++ で可能ですか?
これは、単純なラッパーで行うことができます。
int main()
{
check();
}
main
標準ではプログラムのエントリポイントとして明示的に指定されているため、他の方法で移植可能にすることはできません。
コメントの編集:これは絶対にしないでください。C++ では、静的初期化中に静的初期化を悪用してcheck
以前main
に呼び出した可能性がありますが、それでもmain
合法的に から呼び出すことはできませんcheck
。あなたはcheck
最初に走ったことができます。コメントに記載されているように、定数初期化子が必要なため、これは C では機能しません。
// At file scope.
bool abuse_the_language = (check(), true);
int main()
{
// No op if desired.
}
さまざまなリンカーには、エントリ ポイントを指定するためのさまざまなオプションがあります。例えば。Microsoft リンカーは/ENTRY:functionを使用します。
/ENTRY オプションは、エントリ ポイント関数を .exe ファイルまたは DLL の開始アドレスとして指定します。
GNU の ldは、コマンド ファイルで -e または ENTRY() を使用します。
言うまでもなく、エントリ ポイントの変更は非常に高度な機能であり、その仕組みを完全に理解する必要があります。1 つには、標準ライブラリの初期化のロードをスキップする可能性があります。
int main()
{
check();
return 0;
}
check
fromからの呼び出しmain
は最も論理的な解決策のように見えますが/ENTRY
、アプリケーションの別のエントリポイントを定義するためにを使用して探索することもできます。詳細については、こちらをご覧ください。
それを達成するための不自然な方法がありますが、それはハックにすぎません。
アイデアは、メイン関数を含む静的ライブラリを作成し、「チェック」関数を呼び出すようにすることです。リンカーは、「プログラム」に対してリンクするときにシンボルを解決します。実際、「プログラム」コードには、それ自体ではメインがありません。
非常に具体的なニーズがない限り、これはお勧めしません (Windows SDK に付属するヘルパー ライブラリには、コマンド ラインの解析などの特定の初期化を実行するメイン関数があるため、Windows スクリーンセーバーが思い浮かびます)。
main の前にコードを実行する方法はありますが、main 以外で開始することはできません。
コードを静的初期化ブロックに入れると、メインの前にコードが実行されます。ただし、100% 制御できるわけではありません。main の前に実行されることは保証できますが、2 つの静的初期化ブロックが両方とも main の前に実行される前に実行される順序を指定することはできません。
リンカーとローダーの両方に、C / C++ プログラムの共有された「理解された」開始として保持される main の概念があります。ただし、 の前に実行されるコードがありますmain
。このコードは、プログラムの「環境のセットアップ」を担当します (セットアップstdin
や などcin
)。コードを静的な初期化ブロックに入れることで、「適切な環境を用意するには、これも行う必要がある」と効果的に言えます。一般に、これは他のアイテムの実行順序で独立して立つことができる小さなものであるべきです。
main の前に 2 つまたは 3 つのことを順番に実行する必要がある場合は、それらを適切な関数にして、main の先頭で呼び出します。
コンパイラによってサポートされている場合があります。たとえば、gcc の場合、-nostartfiles と --entry=xxx を使用して、プログラムのエントリ ポイントを設定できます。デフォルトのエントリ ポイントは _start で、関数 main を呼び出します。
メインが開始する前にオブジェクトを作成することで、メインへの呼び出しを「インターセプト」できます。コンストラクターは関数を実行する必要があります。
#include <iostream>
void foo()
{
// do stuff
std::cout<<"exiting from foo" <<std::endl;
}
struct A
{
A(){ foo(); };
};
static A a;
int main()
{
// something
std::cout<<"starting main()" <<std::endl;
}
私は自分の質問に対する解決策を見つけました。簡単に使用できます
#pragma startup function-name <priority>
#pragma exit function-name <priority>
これらの 2 つのプラグマにより、プログラムは、プログラムの起動時 (メイン関数が呼び出される前) またはプログラムの終了時 (プログラムが _exit によって終了する直前) に呼び出される関数を指定できます。
指定された function-name は、引数を取らず、void を返す、事前に宣言された関数でなければなりません。つまり、次のように宣言する必要があります。
void func(void);
オプションの優先度パラメーターは、64 から 255 の範囲の整数でなければなりません。最高の優先度は 0 です。優先度の高い関数は、起動時に最初に呼び出され、終了時に最後に呼び出されます。優先度を指定しない場合、デフォルトで 100 になります。