• ベストアンサー

C言語で、他の関数で配列を書き換えられないようにしたい

下のCのプログラムでは、func関数は配列aの先頭要素へのポインタを返します。 main関数の側では配列aの中身を表示します。 しかし、main関数のfor文の中の★の部分をコメントアウトせずに入れると、この配列の中身が書き換わってしまいます。  私はfunc関数以外では、この配列の中身をいじられたくないのです。  なんとかfunc関数を工夫して作成して、func関数以外では、配列の中身が変わらないようにしたいのですが、どうすればよいでしょうか。    とは言ったものの、多分できないだろうなあ、という気がします。  できないならばできないでも仕方ないのですが、確信が持てないのです。 条件があります。 funcでは表示は行なわない。 配列aの中身を表示できるように、funcから呼び出し元へ、aのアドレスまたはaの先頭要素のアドレスがわかるような情報を返す。 #include <stdio.h> char *func(int i) { static char a[]="AAAA"; a[i]='z'; return a; } int main(void) { int i; for(i=0; i<4; i++) { char *p=func(i); /* p[i]='X'; ★配列の中身を書き換えてしまう。 */ puts(p); } return 0; }

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

  • ベストアンサー
  • onosuke
  • ベストアンサー率67% (310/456)
回答No.3

staticな変数を使う限りは無理な話です。 func内でnon-staticな領域にコピーしたものをreturnする。 仕様を明記し,funcを呼び出した先で別のバッファへコピーして使うよう徹底する。 などの対策をするしかないでしょう。 こういう仕様では,逆にfunc関数以外で使っていた文字列の内容が funcの呼び出しによって意図せず書き換えられてしまう,といった逆のパターンも往々にしてあります。要注意。

noname#2045
質問者

お礼

>無理な話です。 わかりました。OKです。

その他の回答 (3)

  • nagare
  • ベストアンサー率33% (280/831)
回答No.4

funcでAをzに変換して,mainでXに変換していまうのは、当たり前。(皆様の回答どおり) なので、「他の関数で配列を書き換えられないようにしたい」をロジックで実現するのは、無理です(これも回答どおり) これはロジックの話ではなく、仕様の話になります。 「main関数の側では配列aの中身を表示します」 「funcでは表示は行なわない 」 「配列aの中身を表示できるように、funcから呼び出し元へ、aのアドレスまたはaの先頭要素のアドレスがわかるような情報を返す」 という仕様なので、    mainで書き換えることが、仕様と合っていない。  (p[i]='X'; が何をしたいのかわからない・・・・) となります よ

noname#2045
質問者

お礼

ご回答ありがとうございます。 >、「他の関数で配列を書き換えられないようにしたい」をロジックで実現するのは、無理です ということが判明したので私としてはOKです。

noname#30727
noname#30727
回答No.2

const char *func(int i) でいいのでは? puts もそうですが、表示系は基本的に const を受け取るように統一していけばいいと思います。

noname#2045
質問者

補足

標準関数は知らないですが、関数の戻り値の型にconstを使うのは私は見たことがありませんでした。 やってみました。 const char *func(int i) とすると、 mainがわの  char *p=func(i);  で警告が出ましたがエラーにはならず、main関数で書き換えられてしまうことがわかりました。

  • takebou
  • ベストアンサー率43% (27/62)
回答No.1

a[]のポインタを返してしまう以上、書き換えは避けられませんね。 「条件」を無視してしまいますが、 main()で配列を用意して、そのポインタをfunc()に渡す。 func()は受け取ったポインタに加工したa[]をコピーして終了という方法でどうでしょうか? 「条件」がを無視できないから困ってるんですっけ?

noname#2045
質問者

お礼

>a[]のポインタを返してしまう以上、書き換えは避けられませんね。 そうですね。