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

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

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

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

Q&A

3回答

493閲覧

c言語のfor文の途中で配列内の値が置き換わってしまっている

alra

総合スコア0

C

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

0グッド

0クリップ

投稿2022/07/28 07:12

前提

c言語でn日でのm日間単純移動平均のプログラムを書いています。
計算そのものは合っていると思うのですが、2つめのfor文においてi=31からx[i]の値がy[m-1]以降に置き換わってしまっています。
(例 m=20のときx[31]=10と入力しているにもかかわらず、計算の結果y[19]=15となるとx[31]=15と表示される。)
xに代入している訳でもないので全く原因が分かりません。
更に言うとfree関数を最後に入れるとsegmentation faultとなるのですが、それの原因も分かりません。
特に前者ですが、ご教授お願いします。

該当のソースコード

c

1#include<stdio.h> 2#include<stdlib.h> 3int main(){ 4int n, m; 5double *x, *y; 6scanf("%d %d", &n, &m); 7 8x=(double *)malloc(n); 9y=(double *)malloc(n); 10 11for(int i=0; i<n; i++) scanf("%lf", &x[i]); 12 13for(int i=m-1; i<n; i++){ 14 double sum=0; 15 for(int j=0; j<m; j++){ 16 sum=sum+x[i-j]; 17 } 18 y[i]=sum/m; 19 20 printf("%d %.2lf %.2lf\n", i+1, x[i], y[i]); 21} 22return 0; 23}

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

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

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

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

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

guest

回答3

0

もちっと詳しく説明しますと

x=(double *)malloc(n);

おそらく、double型のn個の配列ぶんの領域を確保しようとしている、と推察されますが、
double型というのは、一般的な環境では8バイトの領域を必要とします
ってことで、nバイトでは、確保サイズが足りません

投稿2022/07/28 08:14

y_waiwai

総合スコア87774

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

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

0

double 型の配列、要素数 n 個分のメモリを取得しようとして

C

1 x = (double *)malloc(n); // (X) 2 y = (double *)malloc(n); // (Y)

としたことが間違いなのは、既に他の方々が指摘した通りですが、質問者には状況が見えていないと思います。
このコードで質問者は次のようなメモリ配置を期待したはずです。

イメージ説明

しかし malloc(n) では、このようなメモリ配置になりません。
必要なメモリが確保されず、x と y の領域が重なってしまいます。

x[31]=10と入力しているにもかかわらず、
計算の結果y[19]=15となるとx[31]=15と表示される

これは、x と y の領域が重なった結果、x[31] と y[19] は(名前は違うのに)同じメモリになっている事を示しています。
この状況を再現できる条件は、n == 80 の場合だと推測しました(今時は64bit版コンパイラを使っていると思うので)。そこで、次のコードを試してみてください。

C

1#include<stdio.h> 2#include<stdlib.h> 3 4int main(){ 5 int n = 80; // この値で状況を再現できるだろう 6 double *x, *y, *z; 7 8 // double に必要なバイト数を表示する 9 printf("sizeof(double) = %ld\n", sizeof(double)); 10 11 // メモリを取得する(ここに誤りがある) 12 x = (double *)malloc(n); // (X) 13 y = (double *)malloc(n); // (Y) 14 z = (double *)malloc(n * sizeof(double)); // (Z) 念のため 15 16 // 取得したメモリのアドレスを表示する 17 printf(" x = %p\n y = %p\n\n", x, y); 18 19 // x[] に順に値を格納する 20 for(int i = 0; i < n; i++) 21 x[i] = (double)i; 22 23 // x[] を表示 24 printf("x[] : "); 25 for(int i = 0; i < n; i++) { 26 printf("%.2lf, ", x[i]); 27 } 28 printf("\n\n"); 29 30 // y[] を表示 31 printf("y[] : "); 32 for(int i = 0; i < n; i++) { 33 printf("%.2lf, ", y[i]); 34 } 35 printf("\n\n"); 36 37 // 再確認 38 printf(" x = %p\n y = %p\n", x, y); // x, y は変化しない 39 printf("x[31] = %.2lf (%p)\n", x[31], &x[31]); // x[31] と 40 printf("y[19] = %.2lf (%p)\n", y[19], &y[19]); // y[19] は同一メモリ 41 42 // free() できるか? 43 printf("free(x)\n"); free(x); // x を free() できたとしても 44 printf("free(y)\n"); free(y); // y は free() できないだろう 45 return 0; 46}

私が手元の GCCでコンパイルし、実行させた結果です。

$ ./a.out sizeof(double) = 8 x = 0x55861f7b92a0 y = 0x55861f7b9300 x[] : 0.00, 1.00, 2.00, 3.00, 4.00, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00, 11.00, 12.00, 13.00, 14.00, 15.00, 16.00, 17.00, 18.00, 19.00, 20.00, 21.00, 22.00, 23.00, 24.00, 25.00, 26.00, 27.00, 28.00, 29.00, 30.00, 31.00, 32.00, 33.00, 34.00, 35.00, 36.00, 37.00, 38.00, 39.00, 40.00, 41.00, 42.00, 43.00, 44.00, 45.00, 46.00, 47.00, 48.00, 49.00, 50.00, 51.00, 52.00, 53.00, 54.00, 55.00, 56.00, 57.00, 58.00, 59.00, 60.00, 61.00, 62.00, 63.00, 64.00, 65.00, 66.00, 67.00, 68.00, 69.00, 70.00, 71.00, 72.00, 73.00, 74.00, 75.00, 76.00, 77.00, 78.00, 79.00, y[] : 12.00, 13.00, 14.00, 15.00, 16.00, 17.00, 18.00, 19.00, 20.00, 21.00, 22.00, 23.00, 24.00, 25.00, 26.00, 27.00, 28.00, 29.00, 30.00, 31.00, 32.00, 33.00, 34.00, 35.00, 36.00, 37.00, 38.00, 39.00, 40.00, 41.00, 42.00, 43.00, 44.00, 45.00, 46.00, 47.00, 48.00, 49.00, 50.00, 51.00, 52.00, 53.00, 54.00, 55.00, 56.00, 57.00, 58.00, 59.00, 60.00, 61.00, 62.00, 63.00, 64.00, 65.00, 66.00, 67.00, 68.00, 69.00, 70.00, 71.00, 72.00, 73.00, 74.00, 75.00, 76.00, 77.00, 78.00, 79.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, x = 0x55861f7b92a0 y = 0x55861f7b9300 x[31] = 31.00 (0x55861f7b9398) y[19] = 31.00 (0x55861f7b9398) free(x) free(y) double free or corruption (out) 中止 (コアダンプ)

x[31] と y[19] は、メモリアドレスが同じ、即ち同じメモリであることを示しています。ですから同じ値なのです。


変数はメモリ上に割当てられます。

  • メモリは1バイト(8bit)を単位としてアドレスが割り振られている
  • 変数の型によって変数に必要なメモリサイズは異なる

例えば、sizeof(double) の値は「8」です(表示されています)。
double型は64bitなので、メモリ上では8バイトが必要です。
もし n = 80 の場合、要素数80個分のメモリが必要になりますので、80 * 8 = 640 バイトのメモリが必要です。

  • malloc() の引数は取得しようとするメモリのバイト数を指定する

従って malloc(640) としなければならないのに、(X), (Y) とも malloc(n) 即ち malloc(80) としています。どちらも80バイトしかメモリを取得できず、double の値10個分しか格納できません。
つまり、x[0] ~ x[9] と y[0] ~ y[9] の分しかメモリを取得できていません。
その結果、x, y で取得した領域は次の図のようになります。

イメージ説明

投稿2022/07/30 05:42

rubato6809

総合スコア1380

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

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

0

C

1x=(double *)malloc(n); // n * sizeof(double)

投稿2022/07/28 07:17

ozwk

総合スコア13521

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問