0

私はCから休止を取り、再びそれに戻っています。

doubleの2D配列を作成する場合は、次の2つの方法で作成できます。

double** m_array = (double**) malloc(2*sizeof(double*));
double*  m_array = (double*)  malloc(2*sizeof(double));

また

double array[2][2];

しかし、mallocされた配列を渡すのではなく、他の配列を渡す場合は、次の2つの規則があるようです。

//allowed for passing in malloc'd array, but not for other array
func_m(m_array) //allowed
func_m(array) //disallowed
func_m(double** m_array)

//allowed for passing in either array; required for passing in non-malloc'd array
func(m_array) //allowed
func(array) //allowed
func(double array[][2])

最初は、ポインターの配列へのポインターであること以外の情報は必要ありません。しかし、それはmallocされた配列にしかなり得ません。

2番目では、double*の配列が指す各配列の長さを渡す必要があります。これはばかげているようです。

私は何かが足りないのですか?前もって感謝します。

4

5 に答える 5

6

最初のものは、2次元配列をまったく作成しません。ポインタの配列を作成しますが、これは明らかにどこも指していません。各ポインタを配列に初期化した場合でも、それは2次元配列ではなく、配列の配列になります。

2次元配列を作成してみませんか?

double* dynamicArray = malloc(rows * columns * sizeof (double));

また

double autoArray[rows][columns];

次に、この関数でどちらかを使用できます。

void func(double* array, size_t rows, size_t columns);
于 2010-10-02T23:28:55.693 に答える
2

明確にするために、次のように宣言するとします。

int my_static_array[row][col];

pmgの回答では、my_static_arrayとmallocされた配列(my_malloc配列と呼びましょう)のタイプは何ですか?my_static_arrayは、メモリ内の連続したrow * col * sizeof(int)バイト数であり、先頭へのint*ポインタがあります。my_static_array [x] [y]を計算するとき、コンパイラーは実行することを認識しています(行優先の順序で格納されているため)。

*(addr(my_static_array) + [sizeof(int)*col*x] + [sizeof(int)*y])

これが、Cのcol値を渡す必要がある理由です。

(1) func(int my_static_array[][col])
(2) func(int my_static_array[][])

(1)では、コンパイラは静的配列のアドレスを正しく計算する方法を知っています。(2)では、コンパイラに十分な情報がありません。これが、(1)コンパイルし、(2)コンパイルしない理由です。

ただし、mallocされた配列の場合は、次のように渡すことができます。

func(int** my_malloc_array)

これは1D配列の連続した配列へのポインターであるため、コンパイラーは助けを必要としません。my_malloc_array [x] [y]は単純に実行されます:

*(*(addr(my_malloc_array)+x)+y)

コンパイラは、計算するためにその次元に関する他の情報を必要としません。

それで、レッスンは何ですか?2D配列は、1D配列へのポインターの配列と同じではありません。前者のタイプはint(* my_static_array)[row *col]-行*col要素の配列へのポインターであり、後者のタイプはint**-ポインターの配列へのポインターです。

于 2010-10-03T06:46:52.283 に答える
0

2D配列の割り当てが間違っています。通常の2Dの方法は

double **m_array = malloc(NROWS * sizeof *m_array);
for (i = 0; i < NROWS; i++) {
  m_array[i] = malloc(NCOLS * sizeof *m_array[i]);
}

配列またはポインター(任意の次元)を関数に渡すときは、関数に次元を通知する必要があります。これらは、配列またはポインター自体にエンコードされていません。

一方では、あるタイプへのポインター(ポインター(ポインター(...))へのポインター)があり、他方では、あるタイプの((配列(...))の配列の)配列があります。

関数へのポインタを渡すと、まさにそれが起こります。「配列を渡す」と、配列が最初の要素へのポインタに減衰します。それで

foo(array); // is the same as foo(&(array[0]));

多次元配列の場合array、減衰したポインターのタイプは次のようになりますpointer to array[size] of SOMETHING(ただし、そのサイズは使用できません!)。

簡単な方法は、単純なポインターを使用して関数を記述し、すべての次元の乗算を渡すことです。

double array[3][4][5];
foo(&(array[0][0][0]), 3*4*5);
于 2010-10-02T23:41:15.060 に答える
0

コンピュータのメモリが、順番に番号が付けられたボックスでいっぱいの倉庫であるとします。あなたがするとき

int matrix[10][3];

行列値を保持するために30個のボックスを予約します(たとえば、ボックス131から160まで)。

ここで、関数内の行列のすべての値を合計するとします。

int matrix_sum(int matrix[10][3]) { /* ... */ }

ただし、(標準で義務付けられている)関数が受け取るのは、行列の最初の要素へのポインター、つまり3int秒の配列へのポインターです。したがって、関数はボックス131、132、および133が行列に属していることを認識していますが、行列が実際にどのくらいの長さであるかは認識していません。

于 2010-10-03T12:14:14.830 に答える
0

単純なtypedefを使用します。

typedef double Twodouble_t[2];

void func(Twodouble_t *ptr)
{
  size_t i, numelements = sizeof*ptr/sizeof**ptr;
  puts("first array");
  for( i=0; i<numelements; ++i )
    printf("\n%f",ptr[0][i]);
}
...
Twodouble_t array[]={ {1., 1.},{2., 2.},{3.,3.} };
func(array);
...
于 2010-10-04T21:52:11.073 に答える