web-dev-qa-db-ja.com

argvの最後に常にnullがあるのに、なぜargcが必要なのですか?

argv[argc]は常にNULLなので、argcなしで引数リストを走査できると思います。単一のwhileループがこれを行います。

NULLの最後にargvが常にある場合、なぜargcが必要なのですか?

113
StarPinkER

はい、 argv[argc]==NULLは保証されています。 C11 5.1.2.2.1プログラムの起動を参照してください(私の強調)

宣言されている場合、メイン関数へのパラメーターは以下の制約に従います。

Argcの値は非負でなければなりません。 argv [argc]はNULLポインターでなければなりません。

したがって、argcを提供することは重要ではありませんが、それでも有用です。とりわけ、正しい数の引数が渡されたことをすばやく確認できます。

編集:質問はC++を含むように修正されました。 n3337ドラフト3.6.1メイン関数は言う

2 ... argcは、プログラムが実行される環境からプログラムに渡される引数の数です。 .... argcの値は非負でなければなりません。 argv [argc]の値は0とする

102
simonc

はい、 argv[argc]は、nullポインターであることが保証されています。 argcは便宜上使用されています。

C99 Rationaleの公式説明を引用して、冗長チェックに注意してください。

国際標準の理由—プログラミング言語— C §5.1.2.2.1プログラムの起動

argcargvの引数としてのmainの指定は、広範囲にわたる従来の慣行を認識しています。 argv[argc]は、一般的な慣行に基づいて、リストの最後に冗長なチェックを提供するためにヌルポインターである必要があります。

43
Yu Hao

これは歴史的な理由と、古いコードとの互換性のためです。もともと、argv配列の最後の要素としてNULLポインターが存在するという保証はありませんでした。ただし、argcにはalwaysが存在します。

18
zentrunix

さまざまな標準で要求されているため、「必要」です。

値は完全に無視できますが、mainの最初のパラメーターなので、パラメーターリストに含める必要があります。 C++(およびおそらく非標準のC方言)では、次のC++スニペットのようにパラメーター名を省略できます(Cに変換しやすい):

#include <stdio.h> // C-compatible include, guarantees puts in global namespace

// program will print contents of argv, one item per line, starting from argv[0]

int main(int /*argc*/, char *argv[]) { // uncomment argc for C

    //(void)argc; // uncomment statement for C

    for (int i=0; argv[i]; ++i) {
        puts(argv[i]);
    }

    return 0;
}

標準Cでは、一般的な警告設定で、未使用のパラメーターは警告を生成します。これは、コードを生成せずに名前を使用する(void)argc;などのステートメントで修正できます。

argcは、カウントを取得するためにパラメーターを徹底的に調べる必要があるため、持っていると便利です。また、長さを持つ配列を持つ多くのプログラミング言語では、argcパラメーターはなく、項目を含む配列のみがあります。

6
hyde