- ベストアンサー
ポインタ配列について
/************配列 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"; は何故実行されないのですか?
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
私の説明が適切じゃなかったようです。 関数void change(char *c) の引数cは、ポインタ型の変数で、これは、main関数に その実態がある文字列(実際にはargv[1])の先頭アドレスを指していますね。 ・まず、strcpy(c,"abc"); や c[0]='a'; とした場合ですが、 この場合は、そのアドレスの中にあるデータ(文字を)を直接書き換え ますので、main関数にも反映されます。 ・一方、c="abc"; とした場合は、ポインタ変数cの値(文字列の位置)を "abc"が配置されているアドレスに書き換えることになります。 このため、もともとcが指していたアドレスにあったデータ(文字)の内容が 変わるわけではなく、main関数には反映されません。 (引数cの値自体が変わっても呼び出し元には反映されません)
その他の回答 (6)
- gimmick
- ベストアンサー率49% (134/270)
change1.cのchange()ではポインタ変数cの指している領域の値を変更します。それに対し、change2.cのchange()ではポインタ変数cの値自体を変更します。change2.cのcはローカル変数なので、cの値が変化したところでmain()の方に影響はありません。なお、以下のようにポインタのポインタを利用すれば"abc"と表示させる事が可能です。(ただし、書き換え禁止領域を指しているので注意が必要です。) void change(char **c) { *c = "abc"; return; }
お礼
ありがとうございます^^ なんかわかったような気がしてきました・・ 参考にして自分でもう一度考えて見ます!
- yatokesa
- ベストアンサー率40% (201/496)
change2.c において、引数 char* c の c は change 関数内の動的変数です。いくら c の値を書き換えても change 関数を抜ければローカル変数(スタックに積まれた変数)は解放されてしまいます。 main () { int a = 1; func (a); printf ("%d\n", a); } func (int b) { b = 9; } 下のプログラムでやっていることはこれと同じ事です。
お礼
ありがとうございます^^
- nightowl
- ベストアンサー率44% (490/1101)
すみません、長々と説明しておいて恐縮ですが、 これを「スコープ」の問題というのは適当ではありませんでした。 MovingWalk さんのおっしゃった通り、ああした形の初期化(代入)は 宣言の時にしか行えません。 また、これもご質問とは直接関係はないのですが、change1.c における change() 中の "abc" は書き換え不可能な領域に置かれていて、 プログラマが自由に代入できる文字の配列とは別種の文字列です。 それを除けば、change() 内の「c="abc";」の結びつきが関数を出れば失われる というのは本当です。失礼しました。
お礼
ありがとうございます^^ でも何故 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)
プログラム change2.c における文字列 "abc" は、 関数 change() の中でのみ生きています。 だから、change() を抜けた次の printf() の時点では "abc" はすでに死んでおり、 *agrv とは縁もゆかりもなくなってしまいます。 これは変数の「スコープ(有効範囲)」の問題ですね。 プログラム change1.c では change() 内で実際に *agrv の要素が 書き換えられてしまうのとは対照的です。 「スコープ」や、「値渡し」と「参照渡し」の違いについても 「C言語FAQ」などで勉強してみてください。 ついでに言えば agrc, agrv はそれぞれ argc(argument count), argv(argument vector) の typo ですね。
- MovingWalk
- ベストアンサー率43% (2233/5098)
>こういう格納は出来ないようになっているものなんですか? そうですね。 char *c="abc"; というように初期化のときできますが、それ以外ではできません。
お礼
ありがとうございます^^ すいません、くだらないことですが、 char *c c="abc"; と char *c="abc"; は何か違いがあったりしますか? char *c c="abc"; でも一応cに文字を格納することができました^^;
- MovingWalk
- ベストアンサー率43% (2233/5098)
c="abc"; → strcpy(c,"abc"); としてください。
お礼
あ、わざわざありがとうございます! 実を言うとそれは大丈夫なのですが、何故ダメなのかという理由を知りたいです^^; こういう格納は出来ないようになっているものなんですか?
お礼
詳しくありがとうございます^^ なんとなく理解できました