[解決済み] char** argvとchar* argv[]のどちらを使うべきですか?
質問
C言語を勉強しているのですが、mainメソッドにこのうちのどれを使ったらいいのか悩んでいます。何か違いがあるのでしょうか?どちらがより一般的ですか?
どのように解決するのですか?
C言語を学習しているのですから、まずは の違い の代わりに、配列とポインタの違いをまず理解することをお勧めします。 共通 のものです。
パラメータと配列の領域では、先に進む前に明確にしておくべきいくつかの混乱したルールがあります。まず パラメータリストで宣言したものは特別に扱われます。 C言語では関数のパラメータとして意味をなさないものが、このような状況にあります。
- パラメータとしての関数
- パラメータに配列
パラメータとしての配列
2つ目の項目はすぐには理解できないかもしれません。しかし、C言語では配列の次元のサイズは型の一部であることを考えると、それは明らかになります(そして、次元のサイズが与えられていない配列は不完全な型を持っています)。つまり,配列を値で受け取る(コピーを受け取る)関数を作るとしたら,それは1つのサイズに対してのみ可能なのです.さらに、配列は大きくなる可能性があり、Cは可能な限り高速であろうとします。
C言語では、これらの理由から 配列の値 は存在しません。配列の値を取得したい場合、代わりに得られるのはその配列の最初の要素へのポインタです。そしてここに実はすでに解決策があるのです。Cコンパイラは、配列のパラメータを前もって無効なものとして描画する代わりに を変換します。 を行い、それぞれのパラメータの型をポインタに変換します。これは非常に重要なので覚えておいてください。パラメータは配列ではなく、それぞれの要素タイプへのポインタになります。
さて、配列を渡そうとすると、代わりに渡されるのは、配列の最初の要素へのポインタです。
エクスカーション パラメータとしての関数
最後に、この問題をよりよく理解するのに役立つと思うので、関数をパラメータとして持とうとしたときにどのような状態になるかを見てみましょう。確かに、最初は何の意味もないでしょう。どうしてパラメータが関数になるのでしょうか?そんなの変数に決まってるじゃないですか。そこで、そうなったときにコンパイラがすることは、やはり を変換します。 に変換することです。 関数ポインタ . 関数を渡そうとすると、代わりにそのそれぞれの関数へのポインタが渡されます。つまり、以下は同じです(配列の例と類似しています)。
void f(void g(void));
void f(void (*g)(void));
を括弧で囲んでいることに注意してください。
*g
が必要であることに注意してください。そうでない場合は
void*
を返す関数へのポインタの代わりに
void
.
配列に戻る
さて、冒頭で配列は不完全な型を持つことができると言いましたが、これはサイズをまだ与えていない場合に起こります。配列のパラメータは存在せず、代わりにどの配列パラメータもポインタであることは既に理解しているので、配列のサイズは重要ではありません。つまり、コンパイラは以下のすべてを翻訳し、すべてが同じものであることを意味します。
int main(int c, char **argv);
int main(int c, char *argv[]);
int main(int c, char *argv[1]);
int main(int c, char *argv[42]);
もちろん、どんなサイズでも入れられるというのはあまり意味がなく、ただ捨てられてしまうだけです。そのため、C99ではこれらの数字に新しい意味を持たせ、括弧の間に他のものを表示できるようにしました。
// says: argv is a non-null pointer pointing to at least 5 char*'s
// allows CPU to pre-load some memory.
int main(int c, char *argv[static 5]);
// says: argv is a constant pointer pointing to a char*
int main(int c, char *argv[const]);
// says the same as the previous one
int main(int c, char ** const argv);
最後の2行は、関数内で "argv" を変更できないことを述べています - それは const ポインタになったのです。しかし、このようなC99の機能をサポートしているCコンパイラはごくわずかです。しかし、これらの機能によって、"array"は実際には1つではないことが明らかになりました。それはポインタです。
警告の言葉
上で述べたことは、配列が パラメータ として得た場合のみです。ローカルな配列を扱う場合、配列はポインタではありません。それは ふるまう なぜなら、先に説明したように、配列はその値が読み込まれたときにポインタに変換されるからです。しかし、ポインタと混同してはいけません。
一つの典型的な例として、次のようなものがあります。
char c[10];
char **c = &c; // does not work.
typedef char array[10];
array *pc = &c; // *does* work.
// same without typedef. Parens needed, because [...] has
// higher precedence than '*'. Analogous to the function example above.
char (*array)[10] = &c;
関連
-
ポインタ定数および定数ポインタ
-
[解決済み] 配列から特定の項目を削除するにはどうすればよいですか?
-
[解決済み] オブジェクトが配列であるかどうかを確認するにはどうすればよいですか?[重複]。
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] static_cast, dynamic_cast, const_cast, reinterpret_cast はいつ使うべきですか?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
-
[解決済み] 簡単な面接問題が難しくなった:1~100の数字が与えられたとき、ちょうどk個の数字が欠けていることを見つけなさい。
-
[解決済み] Javascriptのcall() & apply() vs bind()?
-
[解決済み] インラインで配列を宣言する方法はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] MIPSのネストされたForループと配列の使用
-
[解決済み] stdinとSTDIN_FILENOの違いは何ですか?
-
[解決済み] flexible array member not at end of structエラーの原因は何ですか?
-
[解決済み] なぜmemsetではなくbzeroを使用するのですか?
-
[解決済み] ソケットアクセプト - "開かれているファイルが多すぎる"
-
[解決済み] C関数から文字列を返す
-
[解決済み] C言語における「static」の意味とは?
-
[解決済み] Cコードの単体テスト【終了しました
-
[解決済み] char s[]とchar *sの違いは何ですか?
-
[解決済み] なぜalloca()の使用はグッドプラクティスとみなされないのでしょうか?