アプリ版:「スタンプのみでお礼する」機能のリリースについて

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

A 回答 (14件中1~10件)

へ?


「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

遅くまでお疲れ様。


>「**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[])
この二つは、文法上は違いはありません。
意味はまったく同じですので、どちらで書いても同じ動作をします。
どちらで書くかは好みの問題です。

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

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

void test(char *b)


{
int i=sizeof(b);
strcpy(b,"bbb");
}
実際に動かさずにiに入る値が分かって、なんでそうなるのか説明できるなら理解出来てると思いますよ。
私は駆け出しの時、理解できてなくてバグを出して先輩に説教してもらった事があるんですけどね。。。
    • good
    • 0

どうせなら


void test(char b[20])
{
int i=sizeof(b);
strcpy(b,"bbb");
}
の方がおもしろいかと>#5.
    • good
    • 0

#6さん


お見それしましたw
恥ずかしながら一瞬で何を言われたいのが理解できませんでしたw
(ん? ただの参照渡し? しばらく思考停止。。。 なるほど!って感じでした)

個人的にはその手の話題は超好きなのですが、質問者さんにはちょっと早すぎる気がします。
チームで開発する場合、あえて使用する機会がどれだけあるかですけどね。。。
いい例があれば教えてください。
    • good
    • 0

 次のプログラムがあなたの疑問に役立つかも知れません。



int main(void)
{
const static char *const List[] = /* ポインタの配列 */
{"Apple\r\n" ,
"Banana\r\n" ,
"Chery\r\n" } ;

char **pointer ; /* ポインタのポインタ */

/*************************
* プログラムの始まり *
*************************/

/*=== Put_str() の機能を説明 ===*/

Put_str("Put_str() は、文字列を印刷する関数です。\r\n") ;

/*=== 配列を使う方法 ===*/

Put_str(List[0]) ;
Put_str(List[1]) ;
Put_str(List[2]) ;

/*=== ポインタを使う方法 ===*/

pointer = List ;

Put_str(*pointer++) ;
Put_str(*pointer++) ;
Put_str(*pointer++) ;
}

*** 結果 ***
Put_str() は、文字列を印刷する関数です。
Apple
Banana
Chery
Apple
Banana
Chery
    • good
    • 0

もちろん #6 は「きちんと理解できているかどうか」に使うものであって, 決して初心者向けではないです>#7. 実際問題として読みにくくする以外の効果もありませんし.


初心者向けには
1. 「ポインタ」と「配列」は別物である
2. ただし, 関数の引数に書いたときには「配列」は勝手に「ポインタ」とみなされる
3. 多くの場合「配列名」は「ポインタ」と同じように扱われる
というところでしょうか. 1 を押さえておくことは重要.
元の質問の例では関数 main の引数となっているので, 2つ目の char *argv[] は char **argv と全く同じです.
    • good
    • 0

sizeofは演算子であって関数ではない。

←個人的にはこれが重要
だからsizeof演算子に配列を渡した場合と、関数に配列を渡した場合の違いを見て欲しかったんです。
回りくどすぎたみたいですね。申し訳ないです。

元の質問がどっちか分からなくなりましたね。
最初の質問には
***************************************************************
 main関数の引数で、int main(int argc,char **argv[])とint main(int argc,char *argv[])と書かれている場合がありますが、
「**argv」と「*argv」の意味の違いはどのようなもので、どのように使い分けるのでしょうか。
***************************************************************
と書いてますが、質問者さんの意図が分からないので辞めときます。
自称初心者さんは何が分かっていないかが分かっていないので。
    • good
    • 0
この回答へのお礼

bravheartさん、はじめ多くの方からの回答有り難うございます。
>自称初心者さんは何が分かっていないかが分かっていないので。
#確かに「何が分かっていないかが分かっていない」部分は有ります。

配列は元々アドレス渡しになっているので、「「**argv」と「*argv[]」は同じ意味としても考えられるということでしょうか。

お礼日時:2009/10/20 12:12

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