• ベストアンサー

文字列の受け渡し

先ほど質問したものですが、お願いします。 関数で戻り値として、文字列を扱う場合、 char* sendstr(void){ char* mychar="HELLO!!\n"; return mychar; } ならうまくいきますが、 char* sendstr(void){ char mychar[]="HELLO!!\n"; return mychar; } だと、うまくいきません。 配列の場合、mycharで、ポインタと なると、思うのですが。 後者の方が、分かりやすそうですが、 だめなのでしょうか。 (char*は文字型のポインタで、文字列 へのポインタになるのでしょうか)。

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

  • ベストアンサー
  • ttyp03
  • ベストアンサー率28% (277/960)
回答No.2

まずローカル変数という概念を勉強すべきですね。 関数内のローカル変数の値はその関数を抜けると消滅します。 と書くと語弊がありますが、その変数(アドレス)を参照しても内容は保障されません。 つまり char* mychar も char mychar[] もそのアドレスを戻り値として返却し、呼び出し元でそのアドレスを参照しても期待した値が取得できるとは限りません。 char* mychar と char mychar[] でなぜ動きが異なるかはメモリの割り当て方法の違いだと思います(詳しくは解説しません)。 では文字列を戻したい場合、どのような処理にするかというと引数で渡すことになります。 例) void main( void ) {   char mychar[16];   sendstr( mychar ); } void sendstr( char* mychar ) {   strcpy( mychar, "HELLO!!\n" ); } 呼び出し元で文字列を受け取るための領域を確保しそのアドレスを渡します。 sendstr()ではそのアドレスに文字列をセットするわけです。 と、これが基本ではありますが、質問者さんの方法でも動的メモリを使えば可能です。 例) char* sendstr( void ) {   char* mychar;   mychar = (char*)malloc( 16 );   strcpy( mychar, "HELLOW!!\n";   return mycharl } malloc関数で動的にメモリを確保しそこに文字列をセットします。 mallocで確保したメモリは関数を抜けても消滅しません。 その代わり呼び出し側で確実に解放してあげる必要があります。 例) void main( void ) {   char* mychar;   mychar = sendstr();   free( mychar ); } では、がんばってください。

noname#12299
質問者

お礼

呼び出し元の値を呼び出し側で 操作する、ということかな。 アドレス(クラス)を渡して、アドレス の値を操作するのは、JAVAでやったことが あるので、その考え方でやってみます。

その他の回答 (3)

  • buihyaku
  • ベストアンサー率29% (97/326)
回答No.4

ローカル変数については別の方が説明してくださっていますので、配列とポインタの違いについて補足します。 わたしもしょっちゅう混同してしまうのですが、ポインタと配列は同じように使えることが多いですが同じものではありません。 char* mychar="HELLO!!\n"; この記述ではmycharに格納されるのは文字列へのポインタであって、実体は別のところにあります。 mychar[*]------> "HELLO!!\n" この場合、mychar[1]という記述をした場合、まずmycharに格納されたポインタから実体の位置をみつけ、それに添え字で示された数 1 だけオフセットした位置の文字"E"を指します。(間接メモリ参照による参照) この場合、文字列はコンパイル時にわかっているので静的な領域に格納されており、それへのポインタであるmycharの値を返せば関数の外からでも継続して参照することができます。 これに対し、 char mychar[]="HELLO!!\n"; この記述ではmycharは"HELLO!!\n"という文字列で[初期化]されます。つまりmycharの位置に実際に"HELLO!!\n"が格納されます。 mychar[HELLO!!\n] この場合、mychar[1]という記述をした場合、そのままmycharのインデックス1の要素"E"を返します。(直接メモリ参照による参照) この場合、ローカル変数であるmycharに文字列が格納されているので、その先頭へのポインタを返しても、関数を抜けたとたんにクリアされてしまい、関数の外からはアクセスすることはできません。

noname#12299
質問者

お礼

ローカル変数が戻り値にも ならないところが、まだ、 よく分かりませんが・・。 いろいろ回答をもらいましたので、 これらを参考にして、がんばってみます。 (まだ始めたばかりだし)。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.3

#2の方がすでに、理由を説明されていますが、 関数内で宣言した、変数は、その関数を抜けた後は、参照不可能になります。つまり消滅すると考えてかまいません。これを自動変数といいます。 それを前提として char* sendstr(void){ char* mychar="HELLO!!\n"; return mychar; } の場合は、"HELLO!!\n"の文字列自体は、関数を抜けても存在します。return mycharで返しているのは、"HELLO!!\n"の文字列の先頭アドレスです。従って、正常です。 一方、 char* sendstr(void){ char mychar[]="HELLO!!\n"; return mychar; } の場合は、mychar[]の領域に"HELLO!!\n"の文字を確保します。その後、return mycharとすると、mychar[]の先頭アドレスを返します。ここで、mychar[]は自動変数ですので、この関数を抜けた後は、消滅します。従って、エラーとなります。(正しく表示できません) もし、 char* sendstr(void){ static char mychar[]="HELLO!!\n"; return mychar; } のようにした場合は、これは、静的変数といって、この関数を抜けた後も、その内容が保証されます。 従って、その場合は正常に動作します。

noname#12299
質問者

お礼

まだ完全にはわかりませんが、 自動変数をたよりに、いろいろ 調べてみます。ありがとうございました。

  • tukai
  • ベストアンサー率14% (2/14)
回答No.1

とりあいず後者の方法では駄目な理由は 配列のどの要素を返すかが明示的されていないからです。 っていうか、前者の方が扱いやすのでは?

noname#12299
質問者

お礼

回答ありがとうございます。 (ちなみに、前者はどうも、文字への ポインタに思えてしまうのです。 まだ、慣れていないからだと思います)。

関連するQ&A