107
int main( const int argc , const char[] const argv)

有効な C++項目 #3 に「可能な限り const を使用する」と記載されているように、「これらの「定数」パラメーターを作成しない理由」を考え始めますconst

argcの値がプログラムで変更されるシナリオはありますか?

4

7 に答える 7

118

この場合、履歴が要因です。C はこれらの入力を「定数ではない」と定義し、既存の C コード (のかなりの部分) との互換性が C++ の初期の目標でした。

などの一部の UNIX API はgetopt実際に を操作するため、その理由からも argv[]作成できません。const

(余談:getoptのプロトタイプは、argv[]が指す文字列を変更しないが変更する可能性があることを示唆していますが、Linux のマニュアル ページでは、 がgetoptその引数を並べ替えていることが示されています。グループはこの順列について言及していません。)

装着constargcargvもあまり効果がなく、次のような昔ながらのプログラミング手法が無効になります。

// print out all the arguments:
while (--argc)
    std::cout << *++argv << std::endl;

私はそのようなプログラムを C で書いたことがありますが、私だけではないことを知っています。例をどこかからコピーしました。

于 2013-12-13T03:13:06.477 に答える
38

C 標準 (ISO/IEC 9899:2011) には次のように記載されています。

5.1.2.2.1 プログラムの起動

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

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

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

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

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

¶2 それらが宣言されている場合、main関数へのパラメータは次の制約に従うものとします。

  • の値はargc非負でなければなりません。
  • argv[argc]ヌルポインタでなければなりません。
  • の値がargc0 より大きい場合、 inclusiveargv[0]から argv[argc-1]inclusive までの配列メンバーには、プログラムの起動前にホスト環境によって実装定義の値が与えられる文字列へのポインターが含まれます。その目的は、ホスト環境の他の場所からプログラムを開始する前に決定された情報をプログラムに提供することです。ホスト環境が大文字と小文字の両方の文字を含む文字列を提供できない場合、実装は文字列が小文字で受け取られるようにする必要があります。
  • の値がargc0 より大きい場合、 が指す文字列argv[0] はプログラム名を表します。argv[0][0]プログラム名がホスト環境から利用できない場合、ヌル文字になります。の値がargc1 より大きい場合、 ~ が指す文字列 はプログラム パラメータargv[1]を表します。argv[argc-1]
  • 配列が指すパラメータargcおよびargv文字列はargv、プログラムによって変更可能であり、プログラムの起動からプログラムの終了までの間、最後に格納された値を保持します。

10)したがって、intとして定義された typedef 名で置き換えることがintできargvます char **argv

最後の箇条書きに注意してください。と の両方が変更可能であるべきだargcと言っています。argv変更する必要はありませんが、変更することはできます。

于 2013-12-13T03:25:19.187 に答える
23

argcmain()pre-datesの関数シグネチャのため、通常は定数ではありませんconst

argc はスタック変数であるため、それを変更しても、独自のコマンド ライン処理以外には影響しません。

もちろん、必要に応じて自由に宣言constできます。

于 2013-12-13T03:13:27.567 に答える
8

仮引数の最上位constは、関数型の一部ではありません。好きなように追加または削除できます。関数の実装で引数を使用してできることにのみ影響します。

したがって、argc自由に追加できますconst

ただし、関数シグネチャを変更せずargvに文字データを作成することはできません。constこれは、標準のmain関数シグネチャの 1 つではなく、main関数として認識される必要がないことを意味します。だから、良い考えではありません。


main非おもちゃのプログラムで標準引数を使用しない正当な理由は、Windows では、国際文字を使用したファイル名などの実際のプログラム引数を表すことができないためです。これは、Windows では、Windows ANSI としてエンコードされた非常に強力な規則によるものだからです。GetCommandLineWindows では、 API 関数に関して、より移植性の高い引数アクセス機能を実装できます。


const要約すると、 に追加することを妨げるものは何もありませんargcが、最も有用なconst-ness onargvは非標準main関数を提供し、おそらくそのように認識されません。幸いなことに (皮肉なことに)、移植可能な深刻なコードに標準引数を使用しない十分な理由があります。main簡単に言えば、実際には、英語のアルファベット文字のみを使用して、古い ASCII のみをサポートしています。

于 2013-12-13T04:23:31.070 に答える
4

の署名はmain、 からの歴史的なアーティファクトのようなものCです。歴史的にCはありませんでしたconst

constただし、 const の効果はコンパイル時のみであるため、パラメーターを宣言できます。

于 2013-12-13T03:13:42.780 に答える
1

歴史的な理由は別として、argc と argv を非保持にする正当な理由constは、コンパイラの実装が、main への引数を使用して何をしようとしているのかを認識していないためです。コンパイラの実装は、それらの引数を提供する必要があることを認識しているだけです。

const独自の関数と関連するプロトタイプを定義する場合、作成できるパラメーターと、関数が変更する パラメーターを把握できます。

極端に言えば、すべての関数のすべてのパラメーターを宣言する必要があると宣言できconstます。その後、それらを変更する理由がある場合 (配列を検索するためにインデックスをデクリメントするなど)、ローカルの非const変数を作成する必要があります。const引数の値をそれらの変数にコピーします。これにより、忙しい仕事と余分な LOC が発生し、実際のメリットはありません。適切な静的アナライザーは、引数の値を変更していないかどうかを検出し、パラメーターを にすることをお勧めしますconst

于 2013-12-13T19:32:27.303 に答える