質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

1220閲覧

C言語 malloc関数について

yusuke116462

総合スコア1

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

1グッド

1クリップ

投稿2023/01/15 14:01

C言語のmalloc関数の問題を解いています。
構造体の配列をmalloc関数で確保して、足らなくなったらrealloc関数で追加するということをしたいのですが
この確保した配列の要素数を変数に代入したら0になってしまっているのはなぜなのでしょうか?

コード #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct { char name[64]; int age; int sex; }people; void inputpeople(people[]); void showpeople(people); int main(void) { people *data; int i,size; data = (people*)malloc(sizeof(people) * 10); if (data == NULL) exit(0); size = sizeof(data) / sizeof(data[0]);/*ここのsizeに0が入ってしまう*/ printf("情報を入力して下さい。(入力終了なら年齢に-1)\n"); for (i = 0; i < size; i++) { inputpeople(&data[i]); if (data[i].age == -1) { break; } if (i == size-1) { data = (people*)realloc(data,sizeof(people) * 10); size = sizeof(data) / sizeof(data[0]); } } for (i = 0; i < size; i++) { showpeople(data[i]); } free(data); return 0; } void inputpeople(people *data) { printf("名前を入力:"); scanf("%s", data->name); printf("年齢を入力:");; scanf("%d", &data->age); printf("性別を入力(男なら1、女なら2):"); scanf("%d", &data->sex); } void showpeople(people data) { char sex[64]; printf("名前:%s\n", data.name); printf("年齢:%d歳\n", data.age); if (data.age == 1) { strcpy(sex, "男\n"); } else if (data.age == 2) { strcpy(sex, "女\n"); } else { strcpy(sex, "入力が間違っています。\n"); } printf("性別:%s", sex); }
tf2014👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

sizeof(data) は people *data なのですから ポインタのサイズ(4 とか 8 でしょうか)が返ります。
sizeof(data[0]) は people のサイズ(72 とか 80 とか) ですので、整数同士の割り算で切り捨てられて 0 となります。
おかしいと思われたなら、まず size(data) や size(data[0]) を printf して確認するのが良いと思います。


ご質問のコードでは、 size 変数の使い方が逆です。
malloc/realloc した結果から size を求めるのではなく、 size の値から malloc/realloc する大きさを求めるべきです。
また、きちんとするなら、 realloc が返すアドレスを直接 data に入れてはいけません。
realloc は指定したサイズのメモリが確保出来たら元の領域を解放して新しい領域を返しますが、確保出来なかった場合は元の領域は解放せず NULL を返します。(ちなみに指定したサイズ分増やすわけではありません。また、サイズが同じ/縮小の場合は元の領域を流用して元のアドレスを返す場合もあります。)
返した値を data に入れてしまうと、 NULL だった場合に元の領域を解放することが出来ません。
【C言語】realloc関数|正しい使い方と注意点 メモリ断片化など
さらに、確保したメモリのサイズは入力したデータの数と一致しませんので、表示に size 分ループすると、 20 個分のメモリを確保しても 12 件しか入力しなかった場合、 13 件目以降は無駄にデタラメなデータが表示されてしまいます。

c

1int main(void) { 2 int size = 10; //初期サイズ 3 int last = 0; 4 5 people *data = malloc(sizeof(people) * size); 6 if(data == NULL) exit(0); 7 8 printf("情報を入力して下さい。(入力終了なら年齢に-1)\n"); 9 10 while(1) { 11 inputpeople(&data[last]); 12 if(data[last].age == -1) { 13 break; 14 } 15 16 if(++last == size) { 17 size += 10; 18 people *p = realloc(data, sizeof(people) * size); 19 if(p == NULL) { //realloc エラー 20 free(data); 21 exit(0); 22 } 23 data = p; 24 } 25 } 26 27 for(int i = 0; i < last; i++) { 28 showpeople(data[i]); 29 } 30 31 free(data); 32 33 return 0; 34}

投稿2023/01/15 14:04

編集2023/01/15 16:15
jimbe

総合スコア12775

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yusuke116462

2023/01/15 18:10

rellocは指定した分元の配列から増やすと思っていました。分かりやすい説明ありがとうございます。
guest

0

Text

1sex 2下ネタはよくないと思います。

投稿2023/01/15 15:02

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

C

1size = sizeof(data) / sizeof(data[0]);

そもそもdataは配列ではないのでこれで配列の要素数にはなりません。
dataはポインタ変数ですのでsizeof(data)4(32bit)とか8(64bit)などです。

投稿2023/01/15 14:07

ozwk

総合スコア13532

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問