プロが教えるわが家の防犯対策術!

C言語初心者です。
配列について質問させて頂きます。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int hako[40000][6];
int i,j;

for(i=0; i<40000; i++){
for(j=0; j<6; j++){
hako[i][j]=i;
}
}

printf("%d %d %d %d %d\n",hako[i-1][0],hako[i-1][1],hako[i-1][2],hako[i-1][3],hako[i-1][4]);
return 0;
}

上記のソースであれば問題は無いのですが、int hako[40000][6]が40000を超えるとプログラムが無言で終了します。
恐らくメモリの問題だとは思うのですが(汗
この配列を増やす為にはどうしたら良いのでしょうか?

どうぞ、宜しくお願い致します。

質問者からの補足コメント

  • hako = (int**)malloc(sizeof(int*) * 100000);
    for(i=0; i<100000; i++){
    hako[i] = (int*)malloc(sizeof(int)*5);
    for(j=0; j<6; j++){
    hako[i][j]=i;
    }
    }
    こんなんで回るのですね(^^;
    知ると目から鱗な感じです(汗

      補足日時:2018/05/17 14:22

A 回答 (10件)

それは処理系に依存する話なので、使っているコンパイラが何かを書けばわかる人が回答してくれるでしょう。

    • good
    • 0
この回答へのお礼

fakeflakeさん、ありがとう御座います。
コンパイラはC++Builder 10.2です、「C言語を始めよう!」と言うアプリで作成しているのですが、
実際のコンパイラはBuilderであると認識しています。

お礼日時:2018/05/17 12:08

「C言語 ローカル変数 巨大」とか「C言語 ローカル変数 スタック」とかで検索してみましょう。



・プロセスのスタックサイズを大きくする。(やり方はコンパイラ依存かな)
・動的確保する。
・グローバル変数にする。
・static変数にする。
かなぁ……。
    • good
    • 0
この回答へのお礼

Wr5さん ありがとう御座います。

教えて頂いたキーワードで検索してみたのですが…
む、難しいですね((((^^;
スタックサイズを増やす方法や、具体的な方法を教えて頂けたら助かるのですが(汗
コンパイラ依存と言う事は、このコンパイラではこれが限界と言う事でしょうか?

何も知らない素人で申し訳ありませんが、御教授をお願いします。

お礼日時:2018/05/17 12:34

静的配列はサイズ変更できないし、そもそも巨大なロ-カル変数は


ご法度(スタックのサイズが足りなくなると落ちる)。

また、Cは配列のインデックスをチェックしないし、配列外へのアクセスは
何が起きるか分からないのが、Cの怖いところです。

配列の領域を動的に増やすには mallocなどでメモリを取得し直す
しかありません。
    • good
    • 0
この回答へのお礼

tknakamuriさん ありがとう御座います。

少し理解し始めました、mallocにも辿り付きました(汗
第二配列をmallocで動的にする良いサンプルがあれば御教授下さい。

お礼日時:2018/05/17 13:18

配列をintじゃなく、unsigned shortで宣言したらどうなりますか?これでメモリ使用量が半分になります。

ただし16bit長だから、65535を超える場合は使えませんが。

あと、コンパイラをマイクロソフトのVisualStudioにすれば動いちゃったりするとか…
    • good
    • 0
この回答へのお礼

fakeflakeさん 何度もありがとう御座います。

65535を超えるかもしれないので、難しいかもしれません(^^;
VisualStudioに手を出せる程に余裕がありません(汗
御教授ありがとう御座います。

お礼日時:2018/05/17 13:21

「第二配列」ってなんだろう.



あと, Visual Studio といってもいろいろなものがあります. Express や Community だったら手を出す余裕もあるんじゃないかな.
    • good
    • 0
この回答へのお礼

Tacosanさん 二次元配列でした(^^;

御教授ありがとう御座います。
何とかmallocで二次元配列の使い方が分かり、何とか解決に漕ぎ付きました。

この場を借りて、回答頂いた皆様、ありがとう御座います。
また、困ったら御教授の程を宜しくお願い致します。

お礼日時:2018/05/17 14:20

二次元配列…でしょうかね?>#5



「C言語 多次元配列 malloc」とかで検索すると、多次元配列を動的確保する方法が書かれたページが見つかるでしょう。
全部纏めて取る場合と、1次元配列を個別にmallocで取っていく方法がありますが。
http://pukulab.blog.fc2.com/blog-entry-28.html とか
http://www.booran.com/menu/c/multi_pointer.html とか
# 後者の場合だと連続した領域にならないので注意が必要な上、malloc()/free()の回数が増えるのでキツいでしょうね。
# malloc()した場合に消費されるヒープは要求サイズより多くなるでしょうし。(ライブラリの管理用の分が余計に取られる)

Visual Studioならリンカの設定でスタックサイズが指定できた…はずです。(デフォルト1Mでしたっけね?)
動的確保で面倒だったら…おすすめはしませんがstaticにするかグローバルに取るか…でしょうかねぇ。
    • good
    • 0
この回答へのお礼

Wr5さん ありがとう御座います。

頂いたサイトを参照してみたいと思います。

お礼日時:2018/05/17 14:49

どこかで「スタックのデフォルトサイズは 1 MB」と見た記憶があります>#6. 個人的には 2 MB の方がきりがいいんじゃないかなぁとか思ったりもしますが.



あとちなみに
hako = (int**)malloc(sizeof(int*) * 100000);
for(i=0; i<100000; i++){
hako[i] = (int*)malloc(sizeof(int)*5);
for(j=0; j<6; j++){
hako[i][j]=i;
}
}
はバグってるので注意.
    • good
    • 0
この回答へのお礼

Tacosanさん 質問に書いたソースでは動いたのですが…
本当のプログラムに書き込むと… 落ちました(^^;

やっぱり難しいですねぇ~
まだ全く解決してなかったです(汗

お礼日時:2018/05/17 14:52

https://msdn.microsoft.com/ja-jp/library/8cxs58a …
https://msdn.microsoft.com/ja-jp/library/tdkhxak …
何故か2つオプションがあるようですが…Visual Studio(VC++)では1Mですね。

>hako = (int**)malloc(sizeof(int*) * 100000);
>hako[i] = (int*)malloc(sizeof(int)*5);

malloc()の実行回数がステキなことになるので、ライブラリが管理用に取るメモリもその分増えるので注意しましょう。
# 実装によりますが…「1つ前のメモリブロックの管理用構造体へのポインタ」「次のメモリブロックの管理用構造体へのポインタ」「確保したサイズ」があった場合、ポインタ2つ分とint型(long型?)分余分に取られます。
さらに…malloc()に失敗する可能性も考慮が必要でしょう。
# まぁ、最初に大きく取って…という方法の場合だと「連続した空き領域がないからmalloc()が失敗する」という可能性も出てくるのですが。


>本当のプログラムに書き込むと… 落ちました(^^;

>hako[i] = (int*)malloc(sizeof(int)*5);
取ったのはint型「5個」分で、
>for(j=0; j<6; j++){
このループは「何回」まわりますか?
    • good
    • 0
この回答へのお礼

wr5さん
本当に初歩的な部分で…(^^;
0から何だからと頭にあるのですが、どうしても習性的に1から物事が始まってしまうのですよねぇ(-_-;

教えて頂いたサイトを参照して、

int **hako = (int**)malloc(100000 * sizeof(int*));

for(i=0; i<100000; i++){
hako[i] = malloc(sizeof(int) * 5);
}

ドカンと取って動かしてみました。
取り敢えず、上手く廻っているのかな?
現在実行させている最中です。

ちゃんと終わってくれると嬉しいなぁ(^^;

お礼日時:2018/05/17 16:39

/F はコンパイラドライバーである cl に対するオプション, /STACK は実際にリンクをする link へのオプションだったと思います>#8. つまり


cl /F:10000000 なんとか
と実行すると, リンクのときに
link /STACK:10000000 なんか
と実行する, だったはず.
    • good
    • 0
この回答へのお礼

Tacosanさん 返事が遅れて申し訳ありません。

と、取り敢えず、メモリをガバッと取ってぶん回しています(^^;
コンパイラのオプションでも変更出来るのですね勉強になります。
何だかドンドンハードルが上がってくるなぁ(汗

お礼日時:2018/05/20 12:38

メモリを一気にとって実行するサンプルです。


--------------------------------------
#include <stdio.h>
#include <stdlib.h>
struct mytable {
int hako[40000][6];
};
int main(void)
{
struct mytable *ptr;
int i,j;
ptr = malloc(sizeof(struct mytable));
if (ptr == NULL){
printf("malloc error\n");
return 1;
}
for(i=0; i<40000; i++){
for(j=0; j<6; j++){
ptr->hako[i][j]=i;
}
}
printf("%d %d %d %d %d\n",ptr->hako[i-1][0],ptr->hako[i-1][1],ptr->hako[i-1][2],ptr->hako[i-1][3],ptr->hako[i-1][4]);
return 0;
}
-------------------------------------
実行結果
39999 39999 39999 39999 39999
    • good
    • 0
この回答へのお礼

tatsu99さん ありがとう御座います。

素敵な位に奇麗なソースです!!!
いやぁ~~~ 理解されてえる方は本当に理解しきってますねと。
何も言い様がありません!

こう言うのをスルっと書けるスキルまで登り詰めたい物です♪

感謝、感謝です!

お礼日時:2018/05/20 12:41

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