web-dev-qa-db-ja.com

C ++-char ** argv vs. char * argv []

_char** argv_と_char* argv[]_の違いは何ですか? int main(int argc, char** argv)およびint main(int argc, char* argv[])

彼らは同じですか?特に、最初の部分に_[]_がないこと。

49
Simplicity

それらは完全に同等です。 char *argv[]charへのポインターの配列として読み取る必要があり、配列引数はポインターに降格されるため、charへのポインターへのポインター、またはchar **

これは [〜#〜] c [〜#〜] と同じです。

54
Fred Foo

実際、まったく同じです。

覚えておくべき配列の黄金律は次のとおりです。

"配列の名前は、配列の最初の要素へのポインタです。"

したがって、次を宣言する場合:

_char text[] = "A string of characters.";_

変数「text」は、宣言した文字の配列の最初の文字へのポインタです。つまり、「テキスト」のタイプは_char *_です。 [index]を使用して配列の要素にアクセスするとき、実際にやっているのはindexのオフセットを配列の最初の要素へのポインター、およびこの新しいポインターの逆参照。したがって、次の2行は両方の変数を「t」に初期化します。

_char thirdChar = text[3];
char thirdChar2 = *(text+3);
_

角括弧の使用は、コードをより読みやすくする言語によって提供される便利さです。しかし、ポインターへのポインターなど、より複雑なものについて考え始めるとき、これが機能する方法は非常に重要です。 _char** argv_は_char* argv[]_と同じです。2番目のケースでは「配列の名前は配列の最初の要素へのpointer」であるためです。

これから、なぜ配列インデックスが0から始まるのかがわかるはずです。最初の要素へのポインタは、配列の変数名(再び黄金の規則)に加えて、...何もないオフセットです!

私は友人とここでどちらを使うのが良いかについて議論しました。 _char* argv[]_表記を使用すると、「へのポインターへのポインター」として読み取ることができる_char** argv_表記とは対照的に、これは実際には「文字へのポインターの配列」であることを読者に明確にすることができます。キャラクター"。私の意見では、この後者の表記法は読者にそれほど多くの情報を伝えない。

それらがまったく同じであることを知っているのは良いことですが、読みやすさのために、意図がポインターの配列である場合、_char* argv[]_表記はこれをより明確に伝えていると思います。

24
James Bedford

すべての実用的な目的のために、それらは同じです。これは、引数として渡された配列をC/C++が処理するためです。配列はポインターになります。

3
Erik

質問の最初の部分:

  • char ** argv:charへのポインターへのポインター
  • char * argv []:配列へのポインター

したがって、問題は、タイプCへのポインターと配列C []が同じものかどうかです。一般的にはまったくありませんが、 署名で使用する場合は同等 です。

言い換えれば、あなたの例には違いはありませんが、そうでない場合は、ポインターと配列の違いに留意することが重要です。

3

ブラケット形式は、次のようなステートメント宣言でのみ役立ちます。

char *a[] = {"foo", "bar", "baz"};
printf("%d\n", sizeof a / sizeof *a);
// prints 3

コンパイル時に配列のサイズを知っているためです。関数(メインまたは他の何らかのもの)にパラメーターとしてブラケット形式を渡すと、コンパイラーは実行時に配列のサイズがどうなるか分からないため、char ** aとまったく同じです。私は、char ** argvが好きです。なぜなら、sizeofがステートメント宣言フォームの場合のように機能しないことがより明確だからです。

2
Jake