76

Cのmain関数の有効な署名は実際には何ですか?知っている:

int main(int argc, char *argv[])

他に有効なものはありますか?

4

5 に答える 5

81

C11規格では、次の2つについて明示的に言及しています。

int main(void);
int main(int argc, char* argv[]);

ただし、次の脚注で「または同等の」というフレーズについて言及しています。

したがって、として定義さintれた名前に置き換えることができます。または、のタイプは、などと書くことができます。typedefintargvchar ** argv

さらに、より多くの(実装定義の)可能性も提供します。

関連するテキスト(セクション5.1.2.2.1ですが、この特定の側面はから変更されていませんC99)は次のように述べています。

プログラムの起動時に呼び出される関数の名前はmainです。実装は、この関数のプロトタイプを宣言していません。intこれは、パラメータなしのリターンタイプで定義する必要があります。

int main(void) { /* ... */ }

または2つのパラメーターを使用します(ここでは、argcおよびと呼ばれますargvが、宣言されている関数に対してローカルであるため、任意の名前を使用できます)。

int main(int argc, char *argv[]) { /* ... */ }

または同等のもの; または他の実装定義の方法で。

それらが宣言されている場合、main関数のパラメーターは次の制約に従う必要があります。

  • の値はargc非負でなければなりません。

  • argv[argc]ヌルポインタでなければならない。

  • の値がargcゼロより大きい場合、配列メンバーargv[0]argv[argc-1]は文字列へのポインタが含まれている必要があります。文字列には、プログラムの起動前にホスト環境によって実装定義の値が与えられます。目的は、ホストされた環境の他の場所からプログラムを起動する前に決定された情報をプログラムに提供することです。ホスト環境が大文字と小文字の両方の文字を含む文字列を提供できない場合、実装は文字列が小文字で受信されることを保証する必要があります。

  • の値がargcゼロより大きい場合、が指す文字列argv[0]はプログラム名を表します。argv[0][0]プログラム名がホスト環境から利用できない場合は、ヌル文字になります。の値がargc1より大きい場合、argv[1]throughが指す文字列argv[argc-1]はプログラムパラメータを表します。

  • 配列が指すパラメータargcargv文字列はargv、プログラムによって変更可能であり、プログラムの起動から終了までの間に最後に保存された値を保持する必要があります。

これは、Cプログラムで通常見られるホスト環境用であることに注意してください。5.1.2.1同じ標準で述べられているように、自立型環境(組み込みシステムなど)の制約ははるかに少なくなります。

自立型環境(オペレーティングシステムの利点なしにCプログラムの実行が行われる可能性がある)では、プログラムの起動時に呼び出される関数の名前とタイプは実装によって定義されます。自立型プログラムで利用可能なライブラリー機能は、第4項で要求される最小限のセットを除いて、実装によって定義されます。

于 2010-01-21T09:50:28.603 に答える
24

標準C

ホストされた環境(これは通常の環境です)の場合、C99標準は次のように述べています。

5.1.2.2.1プログラムの起動

プログラムの起動時に呼び出される関数の名前はmainです。実装は、この関数のプロトタイプを宣言していません。intこれは、パラメータなしのリターンタイプで定義する必要があります。

int main(void) { /* ... */ }

または2つのパラメーターを使用します(ここでは、argcおよびと呼ばれますargvが、宣言されている関数に対してローカルであるため、任意の名前を使用できます)。

int main(int argc, char *argv[]) { /* ... */ }

または同等のもの; 9)または他の実装定義の方法で。

9)したがって、intとして定義されたtypedef名に置き換えることができますint。または、のタイプをargvとして記述したりすることもできますchar **argv

C11およびC18規格は、基本的にC99規格と同じです。

標準C++

C++98標準は次のように述べています。

3.6.1主な機能[basic.start.main]

1プログラムには、プログラムの指定された開始点であるmainと呼ばれるグローバル関数が含まれている必要があります。[...]

2実装は、メイン機能を事前に定義してはなりません。この関数はオーバーロードされてはなりません。戻り型はint型でなければなりませんが、それ以外の場合、その型は実装定義です。すべての実装では、次のmainの定義の両方を許可する必要があります。

int main() { /* ... */ }

int main(int argc, char* argv[]) { /* ... */ }

C ++標準は、「[メイン関数]は型の戻り型を持つint必要がありますが、それ以外の場合、その型は実装定義です」と明示的に述べており、C標準と同じ2つのシグネチャを必要とします。したがって、「void main()」はC ++標準では直接許可されていませんが、非標準準拠の実装が代替を許可しないようにすることはできません(標準準拠の実装が標準の拡張として代替を許可することもできません)。

C ++ 03、C ++ 11、C ++ 14、およびC ++ 17標準は、基本的にC++98と同じです。

共通の拡張

従来、Unixシステムは3番目のバリアントをサポートしています。

int main(int argc, char **argv, char **envp) { ... }

3番目の引数は、文字列へのポインタのnullで終了するリストです。各ポインタは、名前、等号、および値(場合によっては空)を持つ環境変数です。これを使用しない場合でも、' extern char **environ;'を介して環境にアクセスできます。この変数は(まだ)POSIXヘッダーで宣言されていません(この回答の以前のバージョンにもかかわらず)。

これは、C規格によって共通の拡張として認識されており、付録Jに記載されています。

###J.5.1環境引数

¶1ホストされた環境では、main関数は3番目の引数を受け取ります。これは、プログラムのこの実行のための環境に関する情報を提供する文字列を指すchar *envp[]、nullで終了するポインタの配列を指します(5.1。 char2.2.1)。

Microsoft C

MicrosoftVS2010コンパイラは興味深いものです。ウェブサイトは言う:

mainの宣言構文は次のとおりです。

 int main();

または、オプションで、

int main(int argc, char *argv[], char *envp[]);

または、mainandwmain関数をvoid戻り値(戻り値なし)として宣言することもできます。voidを返すことを宣言mainまたはwmain返す場合、returnステートメントを使用して終了コードを親プロセスまたはオペレーティングシステムに返すことはできません。mainまたwmainはがとして宣言されているときに終了コードを返すには、関数voidを使用する必要がありexitます。

のプログラムが終了したときに何が起こるか(どの終了コードが親またはo / sに返されるか)は私にはわかりませんvoid main()—そしてMSWebサイトもサイレントです。

main()興味深いことに、MSは、CおよびC++標準で要求される2引数バージョンを規定していません。char **envpこれは、3番目の引数が環境変数のリストへのポインターである3つの引数の形式のみを規定します。

Microsoftのページには、他のいくつかの選択肢もリストされていますwmain()。これには、ワイド文字の文字列などが含まれます。

このページのMicrosoftVS2005バージョンはvoid main()、代替としてリストされていません。MicrosoftVS2008以降のバージョンはそうです。

int main()と同じですかint main(void)

詳細な分析については、CおよびC++で返される内容に対する私の回答の最後を参照してくださいmain()。(私はかつて、この質問はC ++に言及していると考えていたようですが、そうではなく、決してそうしませんでした。C++では、との間int main()に違いはなく、慣用的なC ++です。)int main(void)int main()

Cでは、2つの表記法に違いがありますが、それは難解な場合にのみ気付くでしょう。具体的には、独自のコードから関数を呼び出す場合は違いがmain()あります。これは、Cで実行でき、C++では実行できません。

表記はのint main()プロトタイプを提供しませんが、main()再帰的に呼び出す場合にのみ重要です。を使用int main()すると、後で(同じ関数または別の関数で)記述int rc = main("absolute", "twaddle", 2):し、正式にコンパイラがコードのコンパイルを拒否する程度まで文句を言うべきではありませんが、コードについて合法的に文句を言う(警告する)場合があります-Werror。 GCCは警告をエラーに変換します)。を使用するint main(void)と、後続のtoの呼び出しmain()でエラーが生成されます—関数は引数をとらないと言いましたが、3つ提供しようとしました。もちろん、main()宣言または定義する前に合法的に呼び出すことはできません(C90セマンティクスをまだ使用している場合を除く)—実装はプロトタイプを宣言しませんmain()。注意:C11標準は、両方int main()int main(void)さまざまな例を示しています。どちらもCで有効ですが、微妙な違いがあります。

于 2010-11-25T04:31:49.317 に答える
8

http://en.wikipedia.org/wiki/Main_function_(programming)#C_and_C.2B.2B

通常int main(int argc, char *argv[])のPOSIXに加えint main(int argc, char **argv, char **envp)て、MacOSXでは

int main(int argc, char* argv[], char* envp[], char* apple[]);

もちろん、Macのみです。

Windowsには

int wmain(int argc, wchar_t* argv[], wchar_t* envp[]);

Unicode(実際にはワイド文字)バリアントとして。もちろんありWinMainます。

于 2010-01-21T10:06:45.963 に答える
8

POSIXはexecve()をサポートします。

int main(int argc, char *argv[], char *envp[])

追加された引数は環境、つまりNAME=VALUEの形式の文字列の配列です。

于 2010-01-21T09:53:43.217 に答える
4
int main(void)

一部のOS(たとえば、Windows)では、次のようなものも有効です。

int main(int argc, char **argv, char **envp)

ここでenvp環境を提供します。getenv()

于 2010-01-21T09:52:24.170 に答える