2

正しいポインタを宣言し、2 次元配列にメモリを割り当てて、正しく関数に渡したい。これを正しく機能させるのに問題があり、助けが必要です。

これが私のコードです:

    double **podrucje;
    podrucje=(double **) malloc (sizeof (double *) *123);
    for (i=0;i<(123);i++)
    {                       
        podrucje[i]=(double *) malloc (sizeof (double) * 11);
    }
    for (i=0;i<(123);i++)
    {   
        memset (podrucje[i], 0, 10);
    }

しかし、このコードは機能しません。プログラム全体が台無しになります。そこで、動的割り当てをあきらめて、これを使用することにしました。

    double podrucje[123][11]={0};

しかし、それを送信して関数で使用する方法がわかりません...

4

7 に答える 7

2

memset はバイト単位で機能します。

double **podrucje = (double **) malloc (sizeof (double *) * 123);
for (i = 0; i < 123; i++)
{                       
    podrucje[i] = (double *) malloc (sizeof (double) * 11);
    memset(podrucje[i], 0, sizeof(double) * 11);
}

渡したい場合は、そのように宣言するだけです

void function(double podrucje[123][11]) {
    ...
}
于 2012-06-11T23:02:57.147 に答える
1

malloc を使用するのが最善ですが、2 行目に配列全体を割り当てると、すべてが連続したメモリに割り当てられます。そう

podrucje = (double*) malloc (sizeof (double) * 123 * 11);

その後、最初のループもなくなる可能性があります。そして、配列を 0 に初期化しているようです。その場合は、calloc代わりに を使用mallocして、2 番目のループを削除します。

配列にインデックスを付けるには、次のようなものを使用します

double myitem = podrucje [11 * row + col];

もちろん、定義などを使用して 11 の使用を一貫させる必要がありますが、それはこの回答のポイントではありません。

于 2012-06-11T23:03:07.257 に答える
0

最新のCコンパイラ(C99でも可能)を使用している場合は、可変サイズの実際の2D行列を宣言することもできます。ポインタを使用したこのひどいエミュレーションにフォールバックする必要はありません。

void myfunc(size_t n, size_t m, double podrucje[n][m])
{
    ...
}

double (*podrucje)[n] = malloc(sizeof(double[n][m]));
myfunc(n, m, podrucje);

関数の場合、行列の前に、の宣言が最初に来ることを確認する必要がありますnm

于 2012-06-12T06:34:40.793 に答える
0

変数定義を書いたのと同じ方法で、関数の引数を書きます。

void myfunc(double podrucje[123][11])
{
    ...
}

double podrucje[123][11];
myfunc(podrucje);

配列は、コピーされるのではなく、「参照によって」渡されることに注意してください。

于 2012-06-11T23:03:05.120 に答える
0

NxM 配列にメモリを動的に割り当てる方法はいくつかあります。ここに2つあります:

M 要素の配列へのポインターを宣言してから、そのmallocN インスタンスを宣言できます。

double (*podrucje)[11] = malloc(sizeof *podrucje * 123);

C89 の時点では、 の結果をキャストする必要はありmallocません。sizeofまた、オペランド toは式*podrucje;であることに注意してください。これにより、 と同じ結果が得られsizeof (double) * 11ます。

podrucje[i][j]他の 2D 配列と同様に、 この配列にインデックスを付けます。暗黙的にポインターを逆参照します (これは と同等podrucje[i]であることを思い出してください)。 a[i]*(a + i)

次のように関数で使用します。

void init(double (*podrucje)[11], size_t rows)
{
  size_t i, j;
  for (i = 0; i < rows; i++)
    for (j = 0; j < 11; j++)
      podrucje[i][j] = 0.0;
}

これは次のように呼ばれます

init(podrucje, 123);

この方法の欠点は、関数が Nx11 配列でしか操作できないことです。可変長配列をサポートする C99 コンパイラまたは C2011 コンパイラを使用している場合は、ランタイム変数として列数を指定できます。

void foo(void)
{
  size_t rows = 123, cols = 11;
  double (*podrucje)[cols] = malloc(sizeof *podrucje * rows);
  if (podrucje)
    init(cols, podrucje, rows);
  ...
}

// cols must be declared before it can be used
// in an array declarator
//
void init(size_t cols, double(*podrucje)[cols], size_t rows)
{
  size_t i, j;
  for (i = 0; i < rows; i++)
    for (j = 0; j < cols; j++)
      podrucje[i][j] = 0.0;
}

配列の操作が完了したら、次のように割り当てを解除します。

free(podrucje);

もう 1 つの方法は、次のように各行を個別に割り当てることです。

size_t rows = 123, cols = 11;
double **podrucje = malloc(sizeof *podrucje * rows);
if (!podrucje)
{
  // malloc failed; handle allocation error here
}
else 
{
  size_t i;
  for (i = 0; i < rows; i++)
  {
    podrucje[i] = malloc(sizeof *podrucje[i] * cols);
    if (!podrucje[i])
    {
      // malloc failed; handle allocation error here
    }
  }
}

そして、次のように関数で使用します。

void foo()
{
  double **podrucje;
  // allocate array as above
  init(foo, rows, cols);
  ...
}

void init(double **podrucje, size_t rows, size_t cols)
{
  size_t i, j;
  for (i = 0; i < rows; i++)
    for (j = 0; j < cols; j++)
      podrucje[i][j] = 0.0;
}

配列の使用が終了したら、次のように割り当てを解除します。

for(i = 0; i < rows; i++)
  free(podrucje[i]);
free(podrucje);

最初の方法では、メモリを単一の連続したブロックとして割り当てます。2 つ目は、それを一連のより小さな不連続なチャンクに割り当てます。配列が特に大きいか、ヒープが特に断片化されている場合、最初の方法は失敗し、2 番目の方法は成功する可能性があります。可変長配列をサポートしていないコンパイラを使用している場合、コンパイル時に列数を指定する必要があるため、最初の方法は柔軟性に欠けます。

同じ索引付け方法が両方の形式でどのように機能するのでしょうか?

最初のケースでは、それぞれpodrucje[i]が の 11 要素の配列ですdoublej他の配列と同様に機能します。2 番目のケースでは、それぞれpodrucje[i]が double へのポインターです。a[i]は として評価されるため、*(a + i)配列のインデックス付けは配列式と同様にポインター式でも機能します。

于 2012-06-13T11:16:38.693 に答える
0
int print_func(char((*p)[26])[10])
{
    int i = 0;
    for (i=0; i < 26 ; i++) {
        fprintf(stderr, "%02d:%.*s\n", i, 10, p[0][i]);
    }
    return (0);
}

int main(void)
{
    int nrow = 26;
    int ncol = 10;
    char((*p)[26])[10] = (char((*)[26])[10])(0);
    char(*q)[10];
    char c = 'a';
    int i = 0;

    p = (char((*)[26])[10])malloc(sizeof(char) * nrow * ncol);
    if ((char((*)[26])[10])0 == p) {
            return (-1);
    }
    for (i=0, q=p[0]; i < nrow ; i++) {
        memset(q, c, sizeof(char) * ncol);
        c++;
        q++;
    }
    for (i=0,q=p[0] ; i < nrow ; i++) {
        fprintf(stderr, "%.*s\n", 10, q);
        q++;
    }

    p[0][8][0]='z';
    getchar();
    print_func(p);
    return (0);
}
于 2012-06-13T11:19:49.510 に答える
0

次のコード スニペットでは、

podrucje[i]=(double *) malloc (sizeof (double) * 11);
for (i=0;i<(123);i++)
{   
    memset (podrucje[i], 0, 10);
} 

1)数字に対して余分な括弧は必要ありません。for123ループ11 は次のようになります。

for (i = 0; i < 123; i++)

2) と を使用する代わり12311。a を定義してMACRO、代わりにそれを使用してみてください。

利点: コードは特殊な番号に依存せず、保守が容易です。特に大規模なコード ベースの場合。

3)コードを読んだ場合、podrucje[i] is allocated a memory of 11 doublesしかし、最後の1つがガベージで構成されている場合と構成されていない場合がある間に、ダブルスmemsetのみに設定している場合。10ここで使用callocします。メモリを割り当てるだけでなく、初期化も行います。

podrucje[i]=(double *) calloc(11,sizeof(double));

また、コードをどのように台無しにしているかを正確に伝えることができれば、より役立つ可能性があります。たとえば、コード スニペットは、その失敗を説明するだけではありません。他の人が問題を調査して解決するのに役立ちます。

于 2012-06-12T04:40:02.737 に答える