• ベストアンサー

C言語 動的なメモリの確保 実行できない

malloc関数を使いメモリを確保しそこへ"ABCD"と記憶させ、ポインタ*Cを使い確保したメモリの内容を表示するプログラムです。 ********************************************* #include <stdio.h> #include <stdlib.h> int main(void) {   int i;   char *C;   C = (char *) malloc (sizeof(char) * 5);   C = "ABCD";   for(i = 0; i < 5; i++){     if(C[i] != NULL){       printf("%s", C[i]);    ←※エラー※     }   }   free(C);   return 0; } ********************************************* 正常にコンパイルできますが実行エラーになります。VCを使いF10のデバッグテストで※のところエラーになります。なぜなのでしょうか?

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

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

C[i] は、char で、%s の要求するchar * ではないから。 あと、 C = (char *) malloc (sizeof(char) * 5); で確保したメモリに文字列を設定するには、 strcpy (または、strncpy,stpcpy)を使います。 C = "ABCD"; したら free(C) は、malloc で確保したのとは違う領域を開放しようとしてエラーになります。(アドレスの代入によって、確保した領域はアクセスできなくなります) printf で文字列を表示するなら printf("%s", C); で 1文字ずつ表示するなら printf("%c",C[i]); でします。

ikepan
質問者

お礼

ご返答ありがとうございます。 strcpy関数を使えば良いという事だけではなく、内部的な動きまで丁寧に教えていただきとても理解できました。おかげで実行できました。

その他の回答 (1)

  • Werner
  • ベストアンサー率53% (395/735)
回答No.2

> C = (char *) malloc (sizeof(char) * 5); ここでポインタ変数Cに、mallocで確保した領域へのポインタが代入されていますが、 > C = "ABCD"; ここで文字列リテラル"ABCD"を指すものに上書きされています。 結果として、mallocで確保した領域へのポインタが分からなくなってしまったので、 後でfreeで開放することができなくなります。(メモリリーク) > C[i] != NULL C[0]やC[1]は、ここでは'A'や'B'などの文字なので ポインタであるNULLと比較するのはおかしいです。 文字である'\0'と比較したほうが意味が通ります。  C[i] != '\0' > printf("%s", C[i]); 先に書いたように、C[i]は文字なので、 文字列(実際は文字列の先頭文字へのポインタ)を要求する%sと合わせて使うとおかしな結果になります。 (エラーの直接の原因はこれでしょう。)  printf("%c", C[i]); もしくはループさせずに  printf("%s", C); とするべきです。 > free(C); 先に書いたように、Cはこの時点で文字列リテラル"ABCD"を指しているので、 freeすると問題が発生するかもしれません。

ikepan
質問者

お礼

ご返答ありがとうございます。 No,1様の回答にはなかった他の箇所の指摘と動きの説明までしていただき、とても理解できました。おかげで実行できるようになりました。

関連するQ&A