• ベストアンサー

ポインタについて

C言語では char *p; と宣言しておいてそのポインタに p = "ABC"; というように指定できると思います。 参考URL http://www9.plala.or.jp/sgwr-t/c/sec10-3.html このようにしてポインタを使用した場合、freeで開放する必要はあるのでしょうか。 配列で文字列を指定した場合 char str[] = "ABC"; スタック領域に確保されるので、宣言したメソッドが終わった場合、自動的に開放されると思いますが、malloc等でヒープ領域にメモリを確保した場合、freeで開放されるまではメモリ上に残っていると思います。 動きを見てみると、 char *p; p = "ABC"; もメソッドが終わってもメモリ上に残っているように思えるのですが、 開放する必要があるのでしょうか。 上記のような指定の仕方は使わなければいいだけなのですが、 気になってしまいました。 変な質問ですいませんが、宜しくお願いします。

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

  • ベストアンサー
  • chirubou
  • ベストアンサー率37% (189/502)
回答No.4

開放する/しない、については他の回答者さんの通りです。 「p = "ABC";確保されるとするとこの段階で確保されると思うのですが」 正確に言えば、確保されるのはこの文が実行される時でなく、プログラムの最初から既に確保されています。 int i = 1; とか char *p = "xyz"; とかで指定された「定数」はコンパイル時に認識され、プログラムの「定数領域」(正確には定数領域という呼び方はされていませんが、ここではコンパイラが検出した定数が集められた領域のこととします)に集められています。 例えば、Unix (Linux) では strings というコマンドがあって、プログラムの中に埋め込まれている文字列定数をプリントすることができます。ので、質問者さんのプログラムも "strings a.out" とすると沢山の文字列の中に "ABC" という文字列が表示されるハズです。 勘違いされているのは、 char *p; //定義 test(p); //testメソッドの呼び出し ・・・  //他の処理等 printf( %s, p ); //出力 void test(char *p){ p = "ABC"; // 確保 } とした時、void test(char*) は結果的に何もしていません。char *p = "ABC"; としていますが、変数 p は引数ですので、この関数から戻った時には、呼び出した方に何も影響を及ぼしません。ですからこのプログラムは正しく動きません。 char *p; //定義 p = test(); //testメソッドの呼び出し ・・・  //他の処理等 printf( "%s?n", p ); //出力 char *test(void){ char *p = "ABC"; return( p ); } とでもすべきでしょう。あるいは、ちょっと複雑になりますが、以下のようにすべきでしょう。 char *p; //定義 test(&p); //testメソッドの呼び出し ・・・  //他の処理等 printf( %s, p ); //出力 void test(char **p){ *p = "ABC"; } とすべきです。

take_july
質問者

お礼

有難うございます。 よくわかりました。 既存のソースは構造体の中の一つにポインタを定義してあり、 構造体を受け渡ししていた為、大丈夫なようでした。 (結果的に複雑な方の処理になっていたみたいです。) 自分が例題であげたソースのは空のポインタ(null)を渡してますね。。。 勉強になりました。

その他の回答 (4)

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.5

>確保されるとするとこの段階で確保されると思うのですが、 文字列リテラルはコンパイル時の翻訳フェーズで、 実行文字集合に纏められ、実行時には静的記憶域期間を持ちます。 つまり、文字列リテラルはstaticをつけて宣言された変数と 同じ期間存在することになります。 静的記憶域期間とはプログラムの実行全体となっています。 つまり、プログラムの開始時確保され、終了時に解放されます。

take_july
質問者

お礼

>静的記憶域期間とはプログラムの実行全体となっています。 なるほど、勉強になります。 みなさん素早い回答有難うございました。

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.3

ANo.1の補足について。 "ABC"のような記述に対してはコンパイラはコード領域あるいは静的データ領域に領域を確保しています。これはプログラムの開始から終了まで確保されたままです。 char *p; p = "ABC"; は、このあらかじめ確保された領域の先頭アドレスをポインタ変数pに代入しているだけです。 したがって p[0] = 'a'; のように書き換えてはいけません。仕様上は何が起きるか分かりません。 ちなみに char str[] = "ABC"; は"ABC"が入る大きさ4の文字配列strを確保して"ABC"の内容をコピーしています。 char str[4]; strncpy(str,"ABC",4); と実質的に同じです。 この場合は str[0] = 'a'; のように書き換えてもかまいません。

take_july
質問者

お礼

>"ABC"のような記述に対してはコンパイラはコード領域あるいは静的デ >ータ領域に領域を確保しています。これはプログラムの開始から終了 >まで確保されたままです。 これが知りたかったみたいです。 有難うございました。

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.2

する必要があるなしではなく、開放してはいけません。 freeで開放できるのはmalloc(or realloc)で確保したメモリだけです。 それ以外のものを参照するポインタ(NULLを除く)でfreeを呼び出した場合は何が起きるか分かりません。

  • crew21
  • ベストアンサー率26% (58/222)
回答No.1

結論から言うと無いです。 このような記述をした場合、始めからこれだけのメモリ(4バイト)を含めたコードをコンパイラが生成しますから、プログラム終了時に自動的に介抱されます。

take_july
質問者

補足

ご回答有難うございます。 開放する必要が無いこと分かりました。 まだちょっと分かっていない所があり、 宜しければ教えてください。 char *p; とした場合、この時点ではポインタを定義しているだけですので、 領域はまだ確保されていないと思います。 p = "ABC"; 確保されるとするとこの段階で確保されると思うのですが、 次のように定義した箇所と確保した箇所が違う場合、どこで 開放されるのでしょうか。 char *p; //定義 test(p); //testメソッドの呼び出し ・・・  //他の処理等 printf( %s, p ); //出力 void test(char *p){ p = "ABC"; // 確保 } このように処理を書くと、printfした時点で、"ABC"の領域は確保されているのでしょうか。 それともtestメソッドが終わった時点でスタック領域のように開放されて、使えない場合があるのでしょうか。 既存のソースにこのような記述があるもので。問題なく動いてはいるのですが、気になってしまって。 宜しくお願いします。

関連するQ&A

  • ポインタについて

    C言語のポインタの宣言の仕方についての質問です。お詳しい方どうかご回答よろしくお願いいたします。 (1)char *p; (2)char* p; 上記2つの宣言はどう違うのでしょうか??(同じものなのでしょうか??)メモリの確保の仕方などに違いがあるのでしょうか?? また、この両者はどのように使い分ければ良いかなどお教えください。 よろしくお願いいたします。

  • ポインタ配列の動的確保

    ポインタの配列の動的確保について教えてください。 入力した数値をポインタ配列に入れるプログラムです。 下記のように書いてみました。(見づらくてごめんなさい) #include<stdio.h> #include<stdlib.h> #define kensu 3 main() { char abc[kensu+1]={'A','B','C','\0'}; char *ptr[kensu]; int i; printf("3つの整数を入力して下さい。\n"); for(i=0;i<kensu;i++){ ptr[i]=(char*)malloc(sizeof(char)*10); if(ptr[i]==NULL){ printf("メモリの取得に失敗しました"); exit(1); } printf("整数%c:",abc[i]); fgets(ptr[i],10,stdin); if(ptr[i][strlen(ptr[i])-1]=='\n') ptr[i][strlen(ptr[i])-1]='\0'; } for(i=0;i<kensu;i++) free(ptr[i]); } ちゃんと動いているようです。 しかし、ポインタ配列の動的確保をネットで調べてみると、ポインタのポインタ(?)を使って、下記のように2度mallocしています。 #include <stdio.h> #include <stdlib.h> #define N 3 int main(void) { char** arr; int i,j; arr = (char**)malloc(N * sizeof(char*)); /* ポインタ配列を確保 */ /* 配列の要素それぞれにつき、メモリ領域を確保 */ for(i=0;i<N;i++) arr[i] = (char*)malloc(N * sizeof(char));   ・・・ ポインタの配列を宣言して、配列の各要素に動的確保するのと ポインタのポインタを宣言し、ポインタ配列を動的確保して、再度配列の要素に動的確保するのとでは、何か違いがあるのでしょうか? ポインタのポインタを宣言し、ポインタ配列を確保する必要性が良く分かっていないのです。 ネット等で調べて見たのですが、理解力がないのかよく分かりませんでした。 どうか教えてください。

  • 配列とポインタと同時に使用する宣言について

    配列とポインタを同時に使用した場合、どのように確保されるのかイマイチ理解しきれていません。 例えば、 char *pointer[10]; と宣言した場合、 pointer[0]="ABC" pointer[1]="DEF" ・・・・ のようにポインタ型を配列で管理する、という風に認識しています。 一方で char (*pointer)[10] とした場合、どのように確保されるのでしょうか?

  • ポインタ

    ポインタの勉強をはじめたばかりの者なのですが、たとえば int *p などでポインタを宣言する場合には、メモリ上で変数pにはアドレスを格納するだけの領域が与えられます、このとき何バイトの領域が与えられるのでしょうか?

  • ポインタのポインタの必要性

    書物によるとポインタのポインタの使用例として「ポインタの配列」はポインタを使ってアクセスすることができます。」[*]とありますが、どうしてポインタのポインタが必要なのかがいまいちピンと来ません。 どういう場合なのかを知りたく思っています。 [*]サンプルスクリプト ===================================================== char *mnthp[3] = {/* ポインタの配列の宣言 */ "January", "February", "March" }; char **p1;/* 「ポインタのポインタ」の宣言 */ int i, j; p1=mnthp;/* 「ポインタのポインタ」にポインタの配列 */ /* の先頭番地を設定 */ /***** 例1 *****/ for (i = 0; i < 3; i++) {/* 「ポインタのポインタ」の値を変えずに */ printf("%s\n", *(p1 + i));/* 相対的に文字列を出力 */ } ==> このようなことをしなくとも printf("%s", mnthp[i]); で値を参照出来ると思われる。 ===================================================== [*] http://www9.plala.or.jp/sgwr-t/c/sec10-4.html 宜しくお願い致します。

  • 文字列のメモリ保持期間とポインタについてわからないので教えてください。

    文字列のメモリ保持期間とポインタについてわからないので教えてください。 よくポインタの説明に、文字列を使った下記のようなサンプルコードが紹介されます。 char* s; s = "abcdefg"; printf("%s",s); (http://www2.netf.org/pointer3.html から引用) この"abcdefg"により確保された領域がいつまで保持されるのかわかりません。 ・これを実行しているメソッドを抜けるまでなのか? ・free(s)するまでなのか?(free(s)しなければいけないのか?) この例だとprintfして終わっていますが、sを戻り値として返却して他で利用したり、オブジェクトを生成して、そのメンバ変数に obj1->field1 = "value"; というように格納して利用することとか考えると、領域は勝手に開放されず、やっぱり明示的にfreeするということでしょうか? freeしないといけない、なんて記述も見たことがなくよく理解できずにいます。 よろしくお願いします。

  • ポインタの宣言

    ポインタを宣言するとメモリ上に、ポインタ変数を格納するための領域が確保されます。ポインタ=アドレスというのは大丈夫なのですが、 int *b のようにどうして、ポインタに型があるのでしょうか?単に変数のアドレスを表示するだけならば型はいらないと思うのですが。 またこのとき宣言された変数は *b ではなくて b であってますよね?

  • ポインタで、実装メモリの先頭から100バイト分参照してみたい

    いつもお世話になります。 Cの質問です。 ポインタの勉強中なのですが、ポインタを用いて、実装メモリの先頭から100バイト分を参照してみたい、と思いました。 先輩が言うには「メモリの先頭領域にはメモリのメーカーとか、文字コードが順番に入ってるよ」とのことなのですが、どうにもプログラムが作れません。 mallocでは、どうやら「コンパイル時にメモリ領域を確保する」らしく、指定したメモリ位置(つまりアドレス0)からxxバイト分確保することはできないようです。 私が試しに書いてみたソースは以下になります。 #include<stdio.h> #include<stdlib.h> int main(void){ int i; char *p; p = (char*)malloc(sizeof(char) * 100); for (i=0;i<100;i++){ printf("%c",*p); p++; } return (0); } アドバイスでもかまいませんので、ご指導いただけたらと思います。 よろしくお願いいたします。

  • メモリとポインタと配列と

    malloc()を使用して可変の変数を作り加工。 後々に参照するためにポインタの配列に格納したいと考えております。 malloc()を行った後は必ずfree()にてメモリを開放せねばなりませんが、開放するとポインタの配列に格納した値も消えてしまいます。 だからといって開放せずにいるとメモリリークが起きてしまいます。 この様な場合はどのようにすればよろしいのでしょうか? 大体以下のような処理を考えております。 ご教授願えれば幸いです。 ****************************************   char *p[100];   for(int i=0;i<100;i++) {     char *word1 = "あいう";// ここでは固定文字を代入しているが、実際には何桁の文字列が入るかは不明。     int size = strlen(word1) + 1;     char *memo1 = (char *)malloc(size);     if (memo1 == NULL) {       printf("メモリを割り当てられません\n");       exit(1);     }     strcpy(memo1, word1);          //・     //・ *memo1 を利用した処理。     //・     char *word2 = "abc";// ここでは固定文字を代入しているが、実際には何桁の文字列が入るかは不明。     size = strlen(word1) + 1 + strlen(word2) +1;     char *memo2 = (char *)malloc(size);     if (memo2 == NULL) {       printf("メモリを割り当てられません\n");       exit(1);     }     memset(memo2, 0x00, size); //初期化     strcpy(memo2, word2);     strcat(memo2, "\t");     strcat(memo2, memo1);     p[i] = NULL;     p[i] = memo2;     free(memo2);     free(memo1);   } **************************************** 宜しくお願いします。

  • char型ポインタ

    よくプログラムで charポインタだけ指定して、 #include<stdio.h> int main(){ char* p; p = "abcdef"; printf("%s",p); return 0; } のようにしているのをみかけますが、 メモリーを確保していなくても問題ないのでしょうか? char* p; p = (char*)malloc(7); strcpy(p,"abcdef"); としたのと同じでしょうか?

専門家に質問してみよう