プロが教える店舗&オフィスのセキュリティ対策術

 今晩は、Cの初心者です宜しくお願いします。
 main関数の引数で、int main(int argc,char **argv[])とint main(int argc,char *argv[])と書かれている場合がありますが、
「**argv」と「*argv」の意味の違いはどのようなもので、どのように使い分けるのでしょうか。
また、必ずポインタ型でとるという決まりでしょうか。
宜しくお願いします。

A 回答 (14件中11~14件)

mtake2さんの言われている事に同意します。


>int main(int argc, char **argv)
>int main(int argc, char *argv[])
>この二つは、文法上は違いはありません。

ですが、本題は下記の違いですよね。
int main(int argc, char *argv[])
int main(int argc, char **argv[])


>この内容に、**argv[]、*argv[]の違いのヒントが有るのでしょうか。
ヒントはstrcpy(buf,argv[0]);です。
main関数の宣言を**argv[]と*argv[]で切り替えることでコンパイルエラーの内容や実際の動作に変化はないですか?
(コンパイル時にエラー内容、警告内容を理解するのは必須ですよ)

>#これは、bufのアドレスのあるメモリサイズの大きさが、4と出てると考えていますが???
i = sizeof(buf);
これが10と出力されている事に注目してください。
よく配列を宣言して、その配列を別関数に参照渡し(ポインタで渡す)する場合に下記のコードを書きますが、bufがポインタなら10と出力された事に疑問を持ちませんか?
void test(char *b);
int main(void)
{
char buf[10]="aaa";
test(buf);//この引数のbufはbuf[10]へのポインタではないのか?ポインタならsizeof(buf)の大きさは4byteではないのか?(これが説明できれば理解できています。)
printf("%s",buf);//参照渡し(ポインタでの引き回し)をしているので出力されている値はbbbとなっている。
return 0;
}
void test(char *b)
{
strcpy(b,"bbb");
}

質問者さんへ)
違いを理解するなら、まずは自分でプログラムを組んで、それを動かしてみて、実際に動作を確認して動きを理解することが大切です。
もしデバッグ環境がないのなら、コンソールに出力するなど工夫する事もまたプログラミングの勉強になります。
一度にたくさん理解しようとしないで、1個ずつ理解してください。
    • good
    • 0
この回答へのお礼

bravheartさん、回答有り難う御座います。
>bufがポインタなら10と出力された事に疑問を持ちませんか?
#bufがchar型の配列で要素数が10なら全体のサイズは「1byte*10要素」で10となるのは理解出来るのですが???

宜しくお願いします。

お礼日時:2009/10/18 19:08

変数宣言においては、ポインタと配列は全然別のものですが、


関数の引数では、配列はポインタとして扱われることになっています。そのため、
  int main(int argc, char **argv)
  int main(int argc, char *argv[])
この二つは、文法上は違いはありません。
意味はまったく同じですので、どちらで書いても同じ動作をします。
どちらで書くかは好みの問題です。

それぞれの言い分は
**argv派: 関数の引数に「配列」なんてものはないので、全部ポインタとして書く
*argv[]派: char*の配列=「文字列の配列」であるという設計の意図が分かりやすい
といったところでしょうか。
    • good
    • 1

遅くまでお疲れ様。


>「**argv」と「*argv」の意味の違いはどのようなもので、どのように使い分けるのでしょうか。
違いは文法通りですよ。
main関数に渡される引数をポインタで受け取るか、ポインタのポインタで受け取るかの違いです。
下記のプログラムをデバッグして動きを見てください。(main関数に渡す引数は2個を想定してます。)
void main(int argc,char **argv[])
{
char buf[10]="";
printf("%d\n",argc);
printf("%s\n",argv[0]);//**argv[]の時になぜ正常に動作するかと言うと、printfがポインタのポインタでも動くように賢く作られてるからかな。。。動くがどうかは開発環境に依存するかも知れませんが、あんまり意識しないでください。
printf("%s\n",argv[1]);
printf("%s\n",argv[2]);
strcpy(buf,argv[0]);//コンパイルエラーになるが**argv[]→*argv[]に変えると正常に動作する
}

次になぜポインタのポインタで受け取るかと言う事ですが、Cを書く人のスタイルの差ですw
私は基本的にポインタのポインタは使わないように仕様を決めるので、使用経験が少ないので偉そうに説明するのは辞めときます。(でもコードは理解できますよ)

初心者と自分で言われているので、まずはC言語の最大の難関であるポインタを正しく理解してください。
ちなみにchar buf[10];と宣言したときのbufは特殊な動きをするポインタなので普通のポインタが理解できてから色々プログラムを組んで勉強してください。
ヒントは下記のプログラムです。(iに代入される値に注目)
char buf[10];
char *a=buf;
int i=0;

i=sizeof(buf);
i=sizeof(a);

ポインタのポインタはその次ですね。
    • good
    • 0
この回答へのお礼

bravheartさん、回答有り難う御座います。
早速下のコードで確認して

1
D:\eclipse\workspace\\Pointer\Debug\Pointer.exe
(null)
D
の結果になりましたが、printf("%d\n",argc)、printf("%s\n",argv[0])~("%s\n",argv[2])の内容が出力されているだけで、
この意味がさっぱり分かりません。

この内容に、**argv[]、*argv[]の違いのヒントが有るのでしょうか。
**argv[]、*argv[]の内容は変わらなかったのですが。。。

strcpy(buf,argv[0]);の後にprintf("%s\n",argv[0]);としても何も出力されなかったのですが、警告は出ていましたが???

==========================================================
void main(int argc,char **argv[])
{
char buf[10]="";
printf("%d\n",argc);
printf("%s\n",argv[0]);
printf("%s\n",argv[1]);
printf("%s\n",argv[2]);
strcpy(buf,argv[0]);
}

1
D:\eclipse\workspace\\Pointer\Debug\Pointer.exe
(null)
D
======================================
int main()
{
char buf[10] ;
char *a=buf ;
int i = 0 ;

i = sizeof(buf);
printf("%d\n",i);

i = sizeof(a);
printf("%d\n",i);

return 0;
}
10
4
=======================================================
>(iに代入される値に注目)

 #これは、bufのアドレスのあるメモリサイズの大きさが、4と出てると考えていますが???

これが**argv[]とどのように繋がっていくのでしょうか。

お礼日時:2009/10/18 14:24

へ?


「int main(int argc,char **argv[]) と書かれている場合」というのは, 例えばどこにあるのでしょうか?
int main(int argc,char **argv) ならわかるけど....
    • good
    • 0
この回答へのお礼

Tacosanさん、回答有り難う御座います。

>int main(int argc,char **argv) ならわかるけど....
int main(int argc,char **argv) でした、すみません、どのような意味でしょうか。
宜しくお願いします。

お礼日時:2009/10/18 03:05

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!