dポイントプレゼントキャンペーン実施中!

以下のようなプログラムを作りました。
make_mem関数のなかで構造体のメモリを確保し、
データを代入しています。
しかし、mainに返ってくると値が代入されていません。
よく調べてみると、mainで宣言してあるdataのアドレスが
変更されていません。
どのようにすれば、meake_memoのなかでメモリ確保し、
データを代入できるのでしょうか?
教えてください。

実際の使用しているプログラムはmake_memoのなかで
DBを開き、そのデータを配列に代入しているので、
main関数の中では配列の大きさがわかりません。

#include <stdio.h>
typedef struct {
inta;
intb;
}DATA;

int make_mem(DATA *data){
int i;

data=(DATA *)calloc(10,sizeof(DATA));
printf("calloc %p\n",data);
for (i=0;i<10;i++){
data[i].a = i;
printf("data[%d].a = %d\n",i,data[i].a);
}
return 0;
}

int main(int argc,char *argv[]){
DATA *data;
inti;

printf("before %p\n",data);
make_mem(data);
printf("after %p\n",data);
for (i=0;i<10;i++){
printf("data[%d].a = %d\n",i,data[i].a);
}
return 0;
}

A 回答 (4件)

> freeで開放していないからってことですか?


> この場合はmainのなかでfreeをつかうってことですかね?

この場合は、そうなるとおもいます。

メインの最初でdataをNULLなどで初期化しておいて
メインを終了する前にdataがNULLでなければ
freeするという感じではないでしょうか。
    • good
    • 0
この回答へのお礼

わかりました。
ありがとうございました。

回答してくださった方まとめてのお礼で
申し訳ありませんが、ダブルポインタを
使用する事は目からウロコでした。

ありがとうございました。

お礼日時:2005/01/13 10:55

みなさんがヒントを出されて、


理解されたようですのでそろそろ正解を。
ただし、このまま動かすとメモリリークしますよ。

#include <stdio.h>
typedef struct{
int a;
int b;
}DATA;

int make_mem(DATA **data){
int i;

*data=(DATA *)calloc(10,sizeof(DATA));
printf("calloc %p\n",*data);
for (i=0;i<10;i++){
(*data)[i].a = i;
printf("data[%d].a = %d\n",i,(*data)[i].a);
}
return 0;
}

int main(int argc,char *argv[]){
DATA *data;
int i;

printf("before %p\n",data);
make_mem(&data);
printf("after %p\n",data);
for (i=0;i<10;i++){
printf("data[%d].a = %d\n",i,data[i].a);
}
return 0;
}
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
(*data)[i].a = i;
↑の書き方がわからず、悩んでいました。

>ただし、このまま動かすとメモリリークしますよ。

freeで開放していないからってことですか?

この場合はmainのなかでfreeをつかうってことですかね?

お礼日時:2005/01/13 10:29

まずは簡単なクイズです。

次の結果は?
#include <stdio.h>
void f(int a)
{
a=1;
}
int main(int argc,char** argv)
{
int a=0;
f(a);
printf("%d\n",a);
return 0;
}

答は「0が表示される」です。Cの関数はパラメータが値渡しされるため、パラメータを変更しても元の変数に影響しません。
この辺は理解されてますよね?

では本題。上のaの定義のintをDATA*に変えると?
…そう、パラメータとして受け取った値(この場合DATA *data)は値渡しされているため、関数内で変更しても元の変数に影響を与えません。つまり、ポインタ自体の値が元の関数に渡っていないのです。

解決法は、「ポインタを渡す」です。もうポインタで渡しているよと言われるかもしれませんが、そのポインタのポインタを渡すように変更するのです。つまり、
int make_mem(DATA **data)
に変えるわけです。当然、make_memの内容もそれにあわせて書き換える必要があります。
    • good
    • 0
この回答へのお礼

>この辺は理解されてますよね?

はい。理解しているつもりです

make_memo(DATA *data)になっているのでアドレス渡しに
なっていると思っていました。

>当然、make_memの内容もそれにあわせて書き換える必要があります。

このへんが、よくわからないのですが
調べてみます。

ありがとうございました。

お礼日時:2005/01/13 10:12

DATA *dataを、int dataに置き換えると分かると思います。

関数内部でdataの値を変えても、外に出たときは変わっていませんよね。値渡しといって関数内部で変更しても反映されません。反映させるにはint *dataにしてアドレス渡しにしなければならないのです。
これと同じ要領で、DATA **dataとすればよいです。
…と簡単な説明ですが、参考になれば。
    • good
    • 0
この回答へのお礼

make_memo(DATA *data)になっているのでアドレス渡しに
なっていると思っていました。
ダブルポインタにするってことですね。

ありがとうございました。

お礼日時:2005/01/13 10:09

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!