2011-02-03 10 views
2

私はまだC、malloc、そしてそのすべてのジャズが新しいので、これを書いていくつかのスキルを学ぶことにしました。アイデアは、私はファイルから整数の束を読み込み、それらを行列(2次元配列)に入れています。ファイルの先頭には行数と列数があるので、それらの数値を読み込み、mallocを使って2次元配列を設定します。2次元配列をmallocingするときの問題

int read_matrix(FILE *mat, int ***Z, int *x, int *y) 
{ 
    int i = 0; 
    int x_temp = 0; 
    int y_temp = 0; 

    if (fscanf(mat, "%d %d", &(*x), &(*y)) == EOF){ 
     printf("File is not big enough to contain a matrix\n"); 
     return -1; 
    } 

    printf("About to malloc %d\n", *x); 

    *Z = (int**) malloc(*x * sizeof(int*)); 
    while (i < *x) { 
     printf("mallocing %d\n", i); 
     *Z[i] = (int*) malloc(*y * sizeof(int)); 
     printf("malloced\n"); 
     ++i; 
    } 

    printf("Malloc complete\n"); 

    /*Other unimportant code*/ 
} 

出力が読み:

About to malloc 3 
mallocing 0 
malloced 
mallocing 1 
Segmentation fault 

だから..私は思うZ内の1つのint型**が、何もmallocingないのですか?

私はCについてとても新しいので、少し間違いがあるかどうか、あるいは本当に間違っているかどうかはわかりません。何かご意見は?ありがとう!

+0

'&(* x)'は 'x'と同じです。 – vz0

+0

Ahhhhh yea、ちょうど私が馬鹿hahahであるとして(&x)を無視します。 – cost

答えて

3

[]演算子は、単精度の*演算子よりも密接にバインドされます。 *Z[i](*Z)[i]に変更し、コードが動作するかどうか確認してください。

また、Cでは、(sizex * sizey)サイズの単一配列をmallocして行列にしてから、arr [x * sizey + y]またはarr [y * sizex + x]である。たとえば、int foo[10][10]を宣言した場合、すべての100のintがメモリ内で連続していて、10のint *のリストは格納されていません。

+0

Woot、それは、mallocが完了しました(後で新しいsegの障害で新しい)。ありがとう!制限時間が終わるとあなたを答えとしてマークします – cost

+0

'malloc'は単一の2次元配列で、' int foo [10] [10] 'と同じ構文を保つことができます。最初の次元は整数定数です: 'int(* foo)[10] = malloc(10 * sizeof foo [0]);' – caf

+0

@cost(&@caf):C99準拠のコンパイラを使用している場合、コンパイル時定数であれば、可変長配列VLAと呼ばれ、ポインタはいわゆる可変可変型(VM)である。これは、スタックに割り当てられたときに時には戸惑うことがありますが、ヒープ上で 'malloc'と同様に割り当てると、これは動的なサイズを扱う最も簡単な解決法です。 –

1

Walterが彼の答えで正しく述べたように、それは私があなたのソースコードでそのデリファレンス/型キャスト地獄の存在を取り除くことをお勧めしたい。mallocの結果をキャストしないでくださいその上で(*Z)[i] = ...、ない*Z[i] = ...

でなければなりません。下型の名前を使用しないでくださいsizeof。以下のように表現する。

*Z = malloc(*x * sizeof **Z); 
... 
(*Z)[i] = malloc(*y * sizeof *(*Z)[i]); 

wilはコードを型に依存せず、はるかに読みやすくします。

fscanfには、&(*x)を使用した理由は別です。これは何らかの奇妙なコーディング基準ですか?

+0

また、あなたのコード[C + +としてコンパイルされません](http://stackoverflow.com/questions/3477741/why-does-c-require-a-cast-for-malloc-but-c-doesnt)ので、私はこれをお勧めしません。 –

+0

mallocの結果をキャストすると、C++でコンパイルされません。 – cost

+0

&(* x)は、コーディングするときに非常にうまく考えていないときにやっているコーディングの種類です。 – cost

2

私はWalterとAndreyTの両方に同意します。これは単なる追加情報です。

​​(int自体の1つの大きなブロックと行インデックスの1つのブロック)ではなく、2つのmalloc()コールだけで離れていくことができます。

*Z = malloc(*x * sizeof (*Z)[0]); 
(*Z)[0] = malloc(*x * *y * sizeof (*Z)[0][0]); 
for (i = 1; i < *x; i++) { 
    (*Z)[i] = (*Z)[0] + i * *y; 
} 
+0

良いキャッチ!これは、呼び出し元が2つの 'free'を呼び出すだけで済むので、契約を変更することに注意してください。 –