回答編集履歴

8

malloc 記事へのリンク追加

2023/01/15 16:15

投稿

jimbe
jimbe

スコア13195

test CHANGED
@@ -8,6 +8,7 @@
8
8
  また、きちんとするなら、 realloc が返すアドレスを直接 data に入れてはいけません。
9
9
  realloc は指定したサイズのメモリが確保出来たら元の領域を解放して新しい領域を返しますが、確保出来なかった場合は元の領域は解放せず NULL を返します。(ちなみに**指定したサイズ分増やすわけではありません**。また、サイズが同じ/縮小の場合は元の領域を流用して元のアドレスを返す場合もあります。)
10
10
  返した値を data に入れてしまうと、 NULL だった場合に元の領域を解放することが出来ません。
11
+ → [【C言語】realloc関数|正しい使い方と注意点 メモリ断片化など](https://marycore.jp/prog/c-lang/realloc/)
11
12
  さらに、確保したメモリのサイズは入力したデータの数と一致しませんので、表示に size 分ループすると、 20 個分のメモリを確保しても 12 件しか入力しなかった場合、 13 件目以降は無駄にデタラメなデータが表示されてしまいます。
12
13
 
13
14
  ```c

7

修正

2023/01/15 14:45

投稿

jimbe
jimbe

スコア13195

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

6

修正

2023/01/15 14:43

投稿

jimbe
jimbe

スコア13195

test CHANGED
@@ -6,7 +6,7 @@
6
6
  ご質問のコードでは、 size 変数の使い方が逆です。
7
7
  malloc/realloc した結果から size を求めるのではなく、 size の値から malloc/realloc する大きさを求めるべきです。
8
8
  また、きちんとするなら、 realloc が返すアドレスを直接 data に入れてはいけません。
9
- realloc はメモリが確保出来たら元の領域を解放して新しい領域を返しますが、確保出来なかった場合は元の領域は解放せず NULL を返します。
9
+ realloc はメモリが確保出来たら元の領域を解放して新しい領域を返しますが、確保出来なかった場合は元の領域は解放せず NULL を返します。(ちなみに**指定したサイズ分増やすわけではありません**。)
10
10
  返した値を data に入れてしまうと、 NULL だった場合に元の領域を解放することが出来ません。
11
11
  さらに、確保したメモリのサイズは入力したデータの数と一致しませんので、表示に size 分ループすると、 20 個分のメモリを確保しても 12 件しか入力しなかった場合、 13 件目以降は無駄にデタラメなデータが表示されてしまいます。
12
12
 

5

修正

2023/01/15 14:34

投稿

jimbe
jimbe

スコア13195

test CHANGED
@@ -8,25 +8,25 @@
8
8
  また、きちんとするなら、 realloc が返すアドレスを直接 data に入れてはいけません。
9
9
  realloc はメモリが確保出来たら元の領域を解放して新しい領域を返しますが、確保出来なかった場合は元の領域は解放せず NULL を返します。
10
10
  返した値を data に入れてしまうと、 NULL だった場合に元の領域を解放することが出来ません。
11
+ さらに、確保したメモリのサイズは入力したデータの数と一致しませんので、表示に size 分ループすると、 20 個分のメモリを確保しても 12 件しか入力しなかった場合、 13 件目以降は無駄にデタラメなデータが表示されてしまいます。
11
12
 
12
13
  ```c
13
14
  int main(void) {
14
15
  int size = 10; //初期サイズ
16
+ int last = 0;
15
17
 
16
18
  people *data = malloc(sizeof(people) * size);
17
19
  if(data == NULL) exit(0);
18
20
 
19
21
  printf("情報を入力して下さい。(入力終了なら年齢に-1)\n");
20
22
 
21
- for(int i = 0; i < size; i++) {
23
+ while(1) {
22
-
23
- inputpeople(&data[i]);
24
+ inputpeople(&data[last]);
24
-
25
- if(data[i].age == -1) {
25
+ if(data[last].age == -1) {
26
26
  break;
27
27
  }
28
28
 
29
- if(i == size - 1) {
29
+ if(++last == size) {
30
30
  size += 10;
31
31
  people *p = realloc(data, sizeof(people) * size);
32
32
  if(p == NULL) { //realloc エラー
@@ -37,7 +37,7 @@
37
37
  }
38
38
  }
39
39
 
40
- for(int i = 0; i < size; i++) {
40
+ for(int i = 0; i < last; i++) {
41
41
  showpeople(data[i]);
42
42
  }
43
43
 

4

追加

2023/01/15 14:25

投稿

jimbe
jimbe

スコア13195

test CHANGED
@@ -1,3 +1,48 @@
1
1
  sizeof(data) は people *data なのですから ポインタのサイズ(4 とか 8 でしょうか)が返ります。
2
2
  sizeof(data[0]) は people のサイズ(72 とか 80 とか) ですので、整数同士の割り算で切り捨てられて 0 となります。
3
3
  おかしいと思われたなら、まず size(data) や size(data[0]) を printf して確認するのが良いと思います。
4
+
5
+ ---
6
+ ご質問のコードでは、 size 変数の使い方が逆です。
7
+ malloc/realloc した結果から size を求めるのではなく、 size の値から malloc/realloc する大きさを求めるべきです。
8
+ また、きちんとするなら、 realloc が返すアドレスを直接 data に入れてはいけません。
9
+ realloc はメモリが確保出来たら元の領域を解放して新しい領域を返しますが、確保出来なかった場合は元の領域は解放せず NULL を返します。
10
+ 返した値を data に入れてしまうと、 NULL だった場合に元の領域を解放することが出来ません。
11
+
12
+ ```c
13
+ int main(void) {
14
+ int size = 10; //初期サイズ
15
+
16
+ people *data = malloc(sizeof(people) * size);
17
+ if(data == NULL) exit(0);
18
+
19
+ printf("情報を入力して下さい。(入力終了なら年齢に-1)\n");
20
+
21
+ for(int i = 0; i < size; i++) {
22
+
23
+ inputpeople(&data[i]);
24
+
25
+ if(data[i].age == -1) {
26
+ break;
27
+ }
28
+
29
+ if(i == size - 1) {
30
+ size += 10;
31
+ people *p = realloc(data, sizeof(people) * size);
32
+ if(p == NULL) { //realloc エラー
33
+ free(data);
34
+ exit(0);
35
+ }
36
+ data = p;
37
+ }
38
+ }
39
+
40
+ for(int i = 0; i < size; i++) {
41
+ showpeople(data[i]);
42
+ }
43
+
44
+ free(data);
45
+
46
+ return 0;
47
+ }
48
+ ```

3

追加

2023/01/15 14:10

投稿

jimbe
jimbe

スコア13195

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

2

追加

2023/01/15 14:08

投稿

jimbe
jimbe

スコア13195

test CHANGED
@@ -1 +1,2 @@
1
1
  sizeof(data) は people *data なのですから ポインタのサイズ(4 とか 8 でしょうか)が返ります。
2
+ sizeof(data[0]) は people のサイズ(72 とか 80 とか) ですので、整数同士の割り算で切り捨てられて 0 となります。

1

修正

2023/01/15 14:05

投稿

jimbe
jimbe

スコア13195

test CHANGED
@@ -1 +1 @@
1
- sizeof(data) は people *data なのですから ポインタのサイズが返ります。
1
+ sizeof(data) は people *data なのですから ポインタのサイズ(4 とか 8 でしょうか)が返ります。