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

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

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

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

Q&A

解決済

3回答

754閲覧

c言語の配列とデータ型

kjhoh

総合スコア4

C

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

0グッド

0クリップ

投稿2022/11/21 15:29

実現したいこと

c言語で以下のソースコードを書いていた時に、16行目の配列x[],y[]にそれぞれ配列の要素数としてscanfで入力したnを入れようとしたとき未知数であるためコンパイルできないというエラーが出ました。この問題を解決することはできないのでしょうか?
また、、16行目の配列x[],y[]にそれぞれ配列の要素数として以下のように定量的な値として、1000000と入れたらプログラムが動かないという問題が発生しました。10000としたときは動いたため、データ型等に問題があるのかと考えましたが、計算途中でもdoubleの範囲を満たしているように見えるため、なぜ動かないかわかりません。
この問題の原因も教えてもらえると嬉しいです。

該当のソースコード

ソースコード #include <stdio.h> int main(void) { int n,i,j,sou,kukaku; i= 0; j= 0; double m; printf("Please input a positive integer.\nn = "); scanf("%d",&n); while(0 < n) { sou=n*n; kukaku=0; double x[20000],y[20000]; while(i < n) { x[i]=(((1.0/n)*i)+((1.0/n)/2)); while(j < n) { y[j]=(((1.0/n)*j)+((1.0/n)/2)); if(((x[i]*x[i]) +(y[j]*y[j])) <= 1) { kukaku++; } j++; } j=0; i++; } printf("総分割数=%d\n",sou); printf("求める区画数=%d\n",kukaku); printf("pi = %.4lf\n",kukaku*4.0/sou); printf("Please input a positive integer.\nn = "); scanf("%d",&n); i=0; j=0; } return 0; } ### 試したこと ここに問題に対して試したことを記載してください。 ### 補足情報(FW/ツールのバージョンなど) ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答3

0

ベストアンサー

動的な配列は古めの c ではできません。
ローカル変数領域はそんなに大きくありません。
どちらの解決にも、 malloc() 等を使用してください。

メモリの動的確保(配列など)

投稿2022/11/21 19:56

編集2022/11/21 20:04
jimbe

総合スコア12646

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

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

0

エラーメッセージは「雰囲気」で読んでいると時々痛い目を見ます。また、コミュニケーションミスを防ぐためにも、質問においてはエラーメッセージは意訳や自分の解釈でなく「出たまま、見たまま」を提示していただきたいと思います。
「未知数であるため」というのは正確ですか? 想像すると「定数式が必要です。」だったのでは。

Cでは、1999年版の規格から配列の宣言時の要素数に変数が使えることになりました。しかし、(多分某一社の抵抗により)その規格は2011年版(だったっけ?)からオプション(対応しなくてもいい)にランクダウンしています。多分質問者さんはその某一社のCコンパイラを使っているのかと思います。
(あるいは、C++では配列の宣言時の要素数は定数でなければいけないので、CのプログラムをC++としてコンパイルしている可能性はありますが)
なので、

この問題を解決する

について(だけ)言えば、要素数に変数を使えるgcc, clang等のコンパイラを採用し、(C++ではなく)Cとしてコンパイルするのが一つの方法です。
コンパイラを変更したくないのなら、jimbeさんが回答しているように、mallocなどを使って自分でメモリを取得してその領域を使うことになるでしょう。

ただし。ローカル変数(関数内で宣言する変数)は、効率や管理の面から「スタック」領域にとられます。スタックは関数呼び出しのときに戻る場所をあくまで一時的な小容量データの退避場所であって、大容量のデータを保存する場所として考えられたものではありません。そのため、現在のWindowsやLinuxでもプログラム全体を通して(デフォルトで)1~2MB程度しか確保されていません。doubleは変数1つあたり8byteを使うのが普通ですから、これを1000000個確保したらそれだけで約8MB, 完全に破綻します。ということで、そもそもその配列の確保の方法は(文法的にエラーを出ないようにしたとしても)ダメ、ということ。
対応案としては、

  1. 要素数の最大値の予想はできるのでしょうか。できるのであれば、最初からその最大値で配列を(関数の外で/グローバル変数として)確保してしまって、余った分は使わない、という手段は考えられます。まぁ、あまりに無駄な確保が多すぎる(GBのオーダーとか)とコンピュータ全体の動作に支障をきたす可能性はありますが。
  2. どうしても「指定されただけ」しか確保したくないというなら、先程の話で出ていたmalloc等による確保をするのがもう一つの方法です。mallocによるメモリ確保はスタックとはまたべつの「ヒープ」という領域を使いますが、これは大容量を使えるのが普通ですので。もちろん、コンピュータが扱えるメモリ量を超えてはだめですけれど。

投稿2022/11/23 10:02

thkana

総合スコア7639

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

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

0

一般的にローカル変数はスタック領域に配置されるため、そんなに大きなサイズは確保できません
グローバル変数にしましょう

投稿2022/11/21 23:03

y_waiwai

総合スコア87774

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問