• ベストアンサー

mallocについて

mallocで得るアドレスの使い方が分からなくて困っています。 void main(){     char *mem;     char *initial_address; /*初期アドレス保持*/     mem = (char*)malloc(5);     printf("malloc mem -> %p\n", mem);     initial_address = mem;     mem = "abcd";     printf("%c - %p\n", *mem, mem);     printf("%c - %p\n", *initial_address, initial_address); } なぜかmem = "abcd";を実行するとmemのアドレスが変わってしまいます。 mallocで得た5byteはmem = "abcd";実行後のアドレスから5byteということでしょうか。。 それとmem = 'a';を実行するとmemのアドレスはなぜか変わりません。 どうか、ご教授よろしくお願いします。m(__)m

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

  • ベストアンサー
  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.2

>なぜかmem = "abcd";を実行するとmemのアドレスが変わってしまいます。 「なぜか」でも何でもなく、メモリ上の"abcd"が格納されているアドレスを代入しているのですから当然です。 確保したメモリに"abcd"を格納したいのであれば、strcpy()なりを使用して「コピー」して下さい。 >mallocで得た5byteはmem = "abcd";実行後のアドレスから5byteということでしょうか。。 違います。 "abcd"は文字列リラテルとして(通常は)書き込み禁止に設定されたデータセクションにあります。 malloc()での確保はヒープ領域から取ります。 # 確保直後はゴミデータが入っています。(calloc()なら0x00で埋められている) >それとmem = 'a';を実行するとmemのアドレスはなぜか変わりません。 書き換わるハズですが…(というかその前にコンパイルエラーになるでしょう) *mem = 'a';ならば、memが指している先頭アドレスの中身が書き換わりますが…。 とりあえず、ポインタについてもう少し勉強された方がよいでしょう。

monyuonyu
質問者

お礼

strcpy,strcat,fgetsを試してうまくいきました。 まさに今勉強中なのでポインタについてもっと勉強します。 メモリの種類と領域についても勉強してみます。 *mem = 'a';のまちがいでした。。よく考えたら可笑しい事にきがつきました。 ご指南とありがとうございました。m(__)m

すると、全ての回答が全文表示されます。

その他の回答 (5)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.6

#5 の補足の蛇足: ISO C に従ういかなる環境においても「char は 1個で 1バイト」です. もちろん「ISO C に従わない環境」なら話は別ですが, 環境に触れないのなら「ISO C に従う」ことは前提にしていいような気がするなぁ. ただし「5」と「5*sizeof(char)」は型が違うので, 後者の方が安全. もっとも, 個人的には sizeof(char) よりも sizeof(*mem) をお勧めするかな. あと, C なら「malloc (など) の返り値のキャスト」はしない.

monyuonyu
質問者

お礼

結構奥が深そうですね。。 sizeof(char) 、 sizeof(*mem)同じような気がしますが、違いを考えてみます。 キャストしなくていいのは初耳です! てっきりmallocの戻り値がvoid*だったりするのかなーと思い込んでいましたが、調べてきます。 ありがとうございましたm(__)m

すると、全ての回答が全文表示されます。
回答No.5

回答ではないのですが、補足として。。。 mallocの引数は、取得したいサイズ(バイト単位)です。 しかし、charは環境によっては必ずしも1バイトとは限りません。 よって、mallocは「[取得したい個数]×[単位サイズ]」を心がけると良いと思われます。 「mem = (char*)malloc(5)」→ 「mem = (char*)malloc(5*sizeof(char))」

monyuonyu
質問者

お礼

sizeof便利そうですね! 積極的に使っていこうとおもいます。 ありがとうございましたm(__)m

すると、全ての回答が全文表示されます。
  • asuncion
  • ベストアンサー率33% (2127/6290)
回答No.4

>mem = "abcd"; ここで、先にmallocで確保してあった領域の先頭アドレス値を 上書きしています。「メモリーリーク」が発生しています。

monyuonyu
質問者

お礼

単語は聞いたことがありましたが、実際どうやって起こるのかなんとなく理解できました。 ありがとうございました。m(__)m

すると、全ての回答が全文表示されます。
  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.3

他の方触れておられないようですが もし"abcde"の5文字をコピーしたいのであれば malloc(6)にしないと例えコピーしてもコピーの段階でメモリ破壊します (動くかもしれませんが潜在的なバグになります) 文字列(5文字)+文字列終端(NULL=1文字)の計6文字分を確保してください

monyuonyu
質問者

お礼

すごく忘れそうです。。 終端文字に気をつけようと思います。 忘れても正常に動いて見えるのが怖いですね@@

すると、全ての回答が全文表示されます。
  • taka37777
  • ベストアンサー率30% (166/544)
回答No.1

mem = (char*)malloc(5); で取得したメモリーアドレスを mem = "abcd"; とすることで、"abcd"をメモリ上に割り当てたアドレスに書き換えているからアドレスが変わります。 「mem="abcd"」を「strcpy(mem, "abcd");」にすれば確保したメモリーにコピーするので、memのアドレスは変わりません。

monyuonyu
質問者

お礼

mem = "abcd";に違和感があったのですが、ようやく理解できました。 関数をつかってメモリにコピーしていこうと思います。 迅速な回答とありがとうございましたm(__)m

すると、全ての回答が全文表示されます。

関連するQ&A