2012-02-10 14 views
3

私は巨大な4D配列ををmallocしようとしている(192ギグ利用可能)カバーの下に1次元配列を使用しました。しかし、何が入ってくるのかは出てくるものと一致しません(下記のassert()を参照してください)。 は(私が定義されたサイズが小さく、しかし本当の番号は、次のとおりです。20,9000,195,120)C:多次元配列

#define SIZE_A 1 
#define SIZE_B 3 
#define SIZE_C 4 
#define SIZE_D 2 

#define offSet(a,b,c,d) (((size_t) SIZE_A * SIZE_B * SIZE_C * a) + ((size_t) SIZE_B * SIZE_C * b) + ((size_t) SIZE_C * c) + d) 

void xall(void) 
{ 
int *aray = (int *) malloc((size_t) SIZE_A * SIZE_B * SIZE_C * SIZE_D * sizeof(int)); 


int counter = 0; 

    for (int a = 0; a < SIZE_A; ++a){ 
     for (int b = 0; b < SIZE_B; ++b){ 
      for (int c = 0; c < SIZE_C; ++c) { 
       for (int d = 0; d < SIZE_D; ++d){ 
        aray[ offSet(a,b,c,d) ] = counter++; 

       }}}} 


counter = 0;  
    for (int a = 0; a < SIZE_A; ++a){ 
     for (int b = 0; b < SIZE_B; ++b){ 
      for (int c = 0; c < SIZE_C; ++c) { 
       for (int d = 0; d < SIZE_D; ++d){  
        int value = aray[ offSet(a,b,c,d) ] ; 
        assert(value == counter++); 

       }}}} 
} 

答えて

1

あなたのマクロはかなり正確ではありません。このように変更します。

#define offSet(a,b,c,d) (((size_t) SIZE_B * SIZE_C * SIZE_D * a) + ((size_t) SIZE_C * SIZE_D * b) + ((size_t) SIZE_D * c) + d) 

あなたは基本的にあなたのSIZE_Xは、1つの文字でオーバーシフトしていました。

私はまた、あなたのマクロのパラメータの周り()を置くことをお勧め:

#define offSet(a,b,c,d) (((size_t) SIZE_B * SIZE_C * SIZE_D * (a)) + ((size_t) SIZE_C * SIZE_D * (b)) + ((size_t) SIZE_D * (c)) + (d)) 
0

私はマクロはこのように定義されなければならないようです。他の人が言及したよう

#define offSet(a,b,c,d) (((size_t) SIZE_B * SIZE_C *SIZE_D * a) + ((size_t) SIZE_C *SIZE_D * b) + ((size_t) SSIZE_D * c) + d) 
5

は、あなたのマクロは、間違っています。それを修正しても問題はありませんが、代わりに、オフセットマクロを手動でローリングするのではなく、多次元配列を直接割り当てることをお勧めします。この例をチェックアウト:

#include <assert.h> 
#include <stdlib.h> 

#define SIZE_A 1 
#define SIZE_B 3 
#define SIZE_C 4 
#define SIZE_D 2 

int main(void) 
{ 
    int counter = 0; 
    int (*array)[SIZE_A][SIZE_B][SIZE_C][SIZE_D] = 
      malloc(sizeof(int) * SIZE_A * SIZE_B * SIZE_C * SIZE_D); 

    for (int a = 0; a < SIZE_A; ++a) 
    for (int b = 0; b < SIZE_B; ++b) 
     for (int c = 0; c < SIZE_C; ++c) 
     for (int d = 0; d < SIZE_D; ++d) 
      (*array)[a][b][c][d] = counter++; 

    counter = 0;  
    for (int a = 0; a < SIZE_A; ++a) 
    for (int b = 0; b < SIZE_B; ++b) 
     for (int c = 0; c < SIZE_C; ++c) 
     for (int d = 0; d < SIZE_D; ++d) 
     { 
      int value = (*array)[a][b][c][d]; 
      assert(value == counter++); 
     } 

    return 0; 
} 

この例では、割り当てられた配列のメモリ内のレイアウトは、それはあなたの質問であるが、なぜコンパイラはあなたのために仕事をさせないとまったく同じですか?さておき社説のビットに

- Cプログラムでmalloc()呼び出しの戻り値をキャストしないでください。 void *からの変換は暗黙的です。明示的キャストを使用すると、暗黙的な関数宣言の警告を隠すことができます。たとえば、stdlib.hを忘れた場合などです。いくつかのOSで

+0

良い点が、問題は、寸法は、Visual Cには大きすぎるです:配列の合計サイズが4ギガバイト以上である、と私は取得アレイサイズが大きすぎるとC2148エラーが発生しました。 – PaeneInsula

+0

しかし、それほど割り当てることができ、それを単純なポインタに割り当てることはできますか?理解できません。 –

+0

あなたの配列が4GBより大きい場合は、より多くのメモリをあなたのコンピュータに入れ、64ビットOSを使用する必要があります。 – mikithskegg

0

、プロセスごとのメモリ割り当ての限界があります。通常、デフォルトが変更されることがあります。

その他、malloc関数を呼び出すときにも、例えばLinuxのような、実メモリを割り当てていない、とあなたはそれへの書き込みをしようとしたときに、後に失敗することがありますが、私は、これはあなたのケースではないと思います。

はあなたが最大のシステム上のプロセスごとのメモリを割り当て制御することができますかどうかをチェックしてみます。 あなたが答えを見つけたら、それは本当に面白いです。

いくつかの読書のもの:

http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory http://www.linux-mag.com/id/827/