• ベストアンサー

ポインタ配列について

/************配列 change1.c ***********/ #include <stdio.h> void change(char *c) { c[0]='a'; c[1]='b'; c[2]='c'; } int main(int agrc, char **agrv) { change(*++agrv); printf("%s",*agrv); return(0); } /**********ポインタ change2.c ***********/ #include <stdio.h> void change(char *c) { c="abc"; } int main(int agrc, char **agrv) { change(*++agrv); printf("%s",*agrv); return(0); } ********************* この2つのプログラムchange1.c,change2.cにおいて、次のようにしたとき結果がこうなります \change1.exe 123 abc \change2.exe 123 123 change2.c において、ポインタでの文字の格納 c="abc"; は何故実行されないのですか?

質問者が選んだベストアンサー

  • ベストアンサー
  • MovingWalk
  • ベストアンサー率43% (2233/5098)
回答No.7

私の説明が適切じゃなかったようです。 関数void change(char *c) の引数cは、ポインタ型の変数で、これは、main関数に その実態がある文字列(実際にはargv[1])の先頭アドレスを指していますね。 ・まず、strcpy(c,"abc"); や c[0]='a'; とした場合ですが、  この場合は、そのアドレスの中にあるデータ(文字を)を直接書き換え  ますので、main関数にも反映されます。 ・一方、c="abc"; とした場合は、ポインタ変数cの値(文字列の位置)を  "abc"が配置されているアドレスに書き換えることになります。  このため、もともとcが指していたアドレスにあったデータ(文字)の内容が  変わるわけではなく、main関数には反映されません。  (引数cの値自体が変わっても呼び出し元には反映されません)

rousei
質問者

お礼

詳しくありがとうございます^^ なんとなく理解できました

その他の回答 (6)

  • gimmick
  • ベストアンサー率49% (134/270)
回答No.6

change1.cのchange()ではポインタ変数cの指している領域の値を変更します。それに対し、change2.cのchange()ではポインタ変数cの値自体を変更します。change2.cのcはローカル変数なので、cの値が変化したところでmain()の方に影響はありません。なお、以下のようにポインタのポインタを利用すれば"abc"と表示させる事が可能です。(ただし、書き換え禁止領域を指しているので注意が必要です。) void change(char **c) {   *c = "abc";   return; }

rousei
質問者

お礼

ありがとうございます^^ なんかわかったような気がしてきました・・ 参考にして自分でもう一度考えて見ます!

  • yatokesa
  • ベストアンサー率40% (201/496)
回答No.5

change2.c において、引数 char* c の c は change 関数内の動的変数です。いくら c の値を書き換えても change 関数を抜ければローカル変数(スタックに積まれた変数)は解放されてしまいます。 main () {  int a = 1;  func (a);  printf ("%d\n", a); } func (int b) {  b = 9; } 下のプログラムでやっていることはこれと同じ事です。

rousei
質問者

お礼

ありがとうございます^^

  • nightowl
  • ベストアンサー率44% (490/1101)
回答No.4

すみません、長々と説明しておいて恐縮ですが、 これを「スコープ」の問題というのは適当ではありませんでした。 MovingWalk さんのおっしゃった通り、ああした形の初期化(代入)は 宣言の時にしか行えません。 また、これもご質問とは直接関係はないのですが、change1.c における change() 中の "abc" は書き換え不可能な領域に置かれていて、 プログラマが自由に代入できる文字の配列とは別種の文字列です。 それを除けば、change() 内の「c="abc";」の結びつきが関数を出れば失われる というのは本当です。失礼しました。

rousei
質問者

お礼

ありがとうございます^^ でも何故 c[0]='a'; といった格納は関数を抜けてもmainで生きているのでしょうか。 c="abc" と c[0]='a'; c[1]='b'; c[2]='c'; c[3]='\n'; は同じだと思っていたのですが^^; cがローカルならc[0..3]もローカルってわけではないのですか?

  • nightowl
  • ベストアンサー率44% (490/1101)
回答No.3

プログラム change2.c における文字列 "abc" は、 関数 change() の中でのみ生きています。 だから、change() を抜けた次の printf() の時点では "abc" はすでに死んでおり、 *agrv とは縁もゆかりもなくなってしまいます。 これは変数の「スコープ(有効範囲)」の問題ですね。 プログラム change1.c では change() 内で実際に *agrv の要素が 書き換えられてしまうのとは対照的です。 「スコープ」や、「値渡し」と「参照渡し」の違いについても 「C言語FAQ」などで勉強してみてください。 ついでに言えば agrc, agrv はそれぞれ argc(argument count), argv(argument vector) の typo ですね。

参考URL:
http://www.catnet.ne.jp/kouno/c_faq/c_faq.html#contents,http://okuyama.mt.tama.hosei.ac.jp/unix/C/slide4-0.html
  • MovingWalk
  • ベストアンサー率43% (2233/5098)
回答No.2

>こういう格納は出来ないようになっているものなんですか? そうですね。 char *c="abc"; というように初期化のときできますが、それ以外ではできません。

rousei
質問者

お礼

ありがとうございます^^ すいません、くだらないことですが、 char *c c="abc"; と char *c="abc"; は何か違いがあったりしますか? char *c c="abc"; でも一応cに文字を格納することができました^^;

  • MovingWalk
  • ベストアンサー率43% (2233/5098)
回答No.1

c="abc";  → strcpy(c,"abc"); としてください。

rousei
質問者

お礼

あ、わざわざありがとうございます! 実を言うとそれは大丈夫なのですが、何故ダメなのかという理由を知りたいです^^; こういう格納は出来ないようになっているものなんですか?

関連するQ&A