int argc、char * argv []はどういう意味ですか?


508

多くのC ++ IDEとコンパイラでは、メイン関数を生成すると、次のようになります。

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

IDEなしでC ++をコーディングするとき、コマンドラインコンパイラーだけで、次のように入力します。

int main()

パラメータなし。これはどういう意味ですか、それは私のプログラムに不可欠ですか?


47
プログラムがコマンドライン引数を無視する場合は、何を書いても問題ありません。プログラムがコマンドライン引数を処理する必要がある場合、IDEは正しく処理しています。
ジョナサンレフラー

30
ハッカーへのヒント:int main(int argc, char* argv[], char* envp[])最後の引数を宣言して出力してみてください。;)
ulidtko

7
@ulidtko初心者にプログラムに脆弱性を導入するように教えるのはよくありません;)
Gab是好人

13
@Gab環境変数の単純な印刷はどのように脆弱性につながりますか?汚染された文字列をそのままsystem()呼び出しやDBクエリなどに渡さないでください。通常どおり、ユーザー入力を使用します。
ulidtko

2
@ulidtko興味深いです。char **envp引数を使用しているときに、汚染された文字列やdbクエリなどを渡す必要がない理由を説明できますか?
マスタージェームズ

回答:


651

argvそしてargcどのようにコマンドライン引数が渡されているmain()CおよびC ++で。

argcが指す文字列の数になりますargv。事実上すべての実装がプログラムの名前を配列の前に付加するため、これは(実際には)1に引数の数を加えたものになります。

変数は慣例によりargc引数の数)とargv引数のベクトル)と名付けられていますが、それらには任意の有効な識別子を与えることができint main(int num_args, char** arg_strings)ます。

int main()コマンドライン引数を処理するつもりがない場合は、完全に省略して、を生成することもできます。

次のプログラムを試してください:

#include <iostream>

int main(int argc, char** argv) {
    std::cout << "Have " << argc << " arguments:" << std::endl;
    for (int i = 0; i < argc; ++i) {
        std::cout << argv[i] << std::endl;
    }
}

./test a1 b2 c3will出力で実行すると

Have 4 arguments:
./test
a1
b2
c3

8
argc0の場合argvもあり、その場合はNULLの場合もあります。標準のAFAIKで許可されています。これを実際に行うシステムについては聞いたことがありませんが、確かに存在する可能性があり、標準に違反することはありません。
Chuck

77
@チャック:「の値はargv[argc]0 でなければならない(C ++ 03§3.6.1/ 2)」ため、argvnull にすることはできません。
James McNellis、2010年

20
@チャック:C(少なくともC99)にも同じ要件があります。
James McNellis、2011年

2
追加する必要があると思いますが、これはほとんどのシステムで同じですが、一部は抽象化されています。たとえば、Pascal / Delphi / Lazarusでは、次のようになります。ParamStrおよびParamCount(メモリが適切に機能する場合)。私の要点は、(もしあれば)他の言語/言語でネイティブアプリケーションを作成する場合、上記が使用するように定義されている可能性が高く、サポートするすべてのシステムで完全に同じ(数/文字列リスト)が機能することです。それら。
クリスチャン

8
@EmilVikströmいいえ、それはおそらくsegfaultを引き起こす深刻なエラーです。*NULLはに等しくありませんNULL
貧弱

52

argcコマンドラインからプログラムに渡される引数の数であり、引数argvの配列です。

あなたはそれらの数を知っている引数をループすることができます:

for(int i = 0; i < argc; i++)
{
    // argv[i] is the argument at index i
}

19

次のように(sh構文を使用して)プログラムを実行するとします。

myprog arg1 arg2 'arg 3'

mainをとして宣言するとint main(int argc, char *argv[])、(ほとんどの環境で)次のmain()ように呼び出されます。

p = { "myprog", "arg1", "arg2", "arg 3", NULL };
exit(main(4, p));

ただし、メインをとして宣言した場合は、int main()次のように呼び出されます

exit(main());

引数が渡されません。

注意すべき2つの追加事項:

  1. これらは、の唯一の標準必須シグニチャですmain。特定のプラットフォームが追加の引数または別の戻り値の型を受け入れる場合、それは拡張機能であり、移植可能なプログラムではこれに依存しないでください。
  2. *argv[]そして**argvあなたが書くことができますので、正確に等価であるint main(int argc, char *argv[])ようにint main(int argc, char **argv)

2
技術的な場合は、実装が2つの定義済みバージョンを提供している場合、実装basic.start.main/2で定義されたの追加バージョンを明示的に許可しmain()ます。したがって、それらは厳密には不適合ではありません。最も一般的なものはでenvp、CとC ++の両方でよく知られているため、C標準のセクションJ.5(共通の拡張機能)の最初のエントリです。
ジャスティン時間-モニカを

1
素敵なペダントリー@Justinをありがとう。回答をより正確に更新しました。
Toby Speight 2017年

わからない- 最小限の再現可能な例を作成して質問することをお勧めします(プロセスが自分で答えるのに十分ではないと想定)。
Toby Speight 2017

9

main起動時にプログラムに提供されたコマンドラインパラメーターを表すパラメーター。argcパラメータは、コマンドライン引数の数を表し、char *argv[]コマンドライン上に設けられた個々の引数を表す文字列(文字ポインタ)の配列です。


2
Argv []は常にnullポインターとしてargv [arg]を持っています。そして、Argv [0]は常に(フルパス)/
nullで

3
@ user3629249:必ずしもそうではありません。argv[0]Cプログラムを起動するプログラムがとして与えたものargv[0]です。Bashの場合、それは実行可能ファイルのパス名であることがよくありますが(おそらく常に)、他のプログラムを実行するプログラムはBashだけではありません。風変わりですが、以下を使用することは許容されますchar *args[] = { "cat", "/dev/null", "/etc/passwd", 0 }; execv("/bin/ls", args);。多くのシステムでは、実行可能ファイルがであっても、プログラムによって見られる値argv[0]はそのままcatです/bin/ls
Jonathan Leffler、2016

7

mainこの関数は2つのパラメータを持ち、できるargcargvargc整数(int)パラメーターであり、プログラムに渡される引数の数です。

プログラム名は常に最初の引数であるため、プログラムには少なくとも1つの引数があり、の最小値はargc1です。しかし、プログラム自体に2つの引数がある場合、の値はargc3 になります。

パラメータargvは文字列配列を指し、引数ベクトルと呼ばれます。これは、関数引数の1次元の文字列配列です。


5
int main();

これは簡単な宣言です。コマンドライン引数を取ることはできません。

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

この宣言は、プログラムがコマンドライン引数を取る必要がある場合に使用されます。そのように実行すると:

myprogram arg1 arg2 arg3

argc、または引数カウントは4(4つの引数)に設定されargv、引数ベクトルは、「myprogram」、「arg1」、「arg2」、および「arg3」への文字列ポインタで埋められます。プログラム呼び出し(myprogram)が引数に含まれています!

または、次のように使用することもできます。

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

これも有効です。

追加できる別のパラメーターがあります。

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

envpパラメータは、環境変数が含まれています。各エントリは次の形式に従います。

VARIABLENAME=VariableValue

このような:

SHELL=/bin/bash    

環境変数リストはnullで終了します。

重要:への呼び出しではargvenvp値や値を直接使用しないでsystem()ください。悪意のあるユーザーが環境変数をコマンドラインコマンドに設定し、(潜在的に)大きな被害を与える可能性があるため、これは大きなセキュリティホールです。通常は、使用しないでくださいsystem()。ほとんどの場合、Cライブラリを通じて実装されるより優れたソリューションがあります。


3

最初のパラメーターは提供される引数の数であり、2番目のパラメーターはそれらの引数を表す文字列のリストです。


7
argv [0]の最初のエントリはプログラム名であり、引数ではありません
user3629249

@ user3629249プログラム名とプログラムパス。;)
マスタージェームズ

1

両方の

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

CまたはC ++プログラムのエントリポイントの正当な定義です。Stroustrup:C ++のスタイルとテクニックに関するFAQでは、メイン関数で可能な、または合法であるいくつかのバリエーションについて詳しく説明しています。


4
互換性と読みやすさのために... int main()==> int main(void)... に空白を入れたいかもしれません。Cのすべての古いバージョンでvoid関数が宣言内に空のパラメーターリストを持つことができるかどうかはわかりません。
dylnmc 2014

1
@dylnmcこれは読みやすさを向上させるものではなく、すべてのC ++バージョンでまったく同じです。Cでのみこれに違いがありますが、宣言ではありますが、定義ではありません。
Ruslan

@Ruslan申し訳ありませんが、私がCを学んでいたときにこれを投稿しました。Cのごく初期のバージョンでは、それvoidが必要であることを読んだかもしれません。それについて私を引用しないでください、そして今私はそれが少しばかげたコメントであることを知っています。ただし、害はありません。
dylnmc 2015年

argc <3がエラーを返す場合はどうなりますか?何がうまくいかなかったのでしょうか?
AVI
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.