2

私は、Cでの多次元の動的に割り当てられた配列の割り当てと使用に関する問題を理解しようとしてきました。助けていただければ、本当にありがたいです。

私は2つのアプローチを試しました。最初:

cdr = (double ***) malloc(NUM_REGIONS * sizeof(double **));
for(i=0; i<NUM_REGIONS; i++){
   cdr[i] = (double **) malloc(numRatings * sizeof(double *));
   for(j=0; j<numRatings; j++){
       cdr[i][j] = (double *) malloc(remQuarters * sizeof(double));
   }
}  

そして2番目:

tempPtr1 = (double *) malloc(NUM_REGIONS * numRatings * remQuarters * sizeof(double) );
tempPtr2 = (double **) malloc (NUM_REGIONS * numRatings * sizeof(double *));
cdr = (double ***) malloc(NUM_REGIONS * sizeof(double **));
for(i=0; i< NUM_REGIONS; i++){
    cdr[i] = tempPtr2 + i;
    for(j=0; j < numRatings; j++) cdr[i][j] = tempPtr1 + i * NUM_REGIONS + j;
}

どちらも機能していません。どちらの場合も、各cdr[i]は最終的に同じ場所を指します。初めて「i」ループに入ると、すべてのcdr [i](つまり、cdr [0]、cdr [1]、cdr [2]など)が同じ値に設定されます。その後のループは、それらのいずれも変更しません。

演算子の優先順位で何かが起こっているか、逆参照が間違っているのではないかと思いますが、それを理解することができませんでした。

ありがとう。

アップデート

次の簡略化されたコードをまとめましたが、これは問題なく機能しているようです。しかし、出力は完全に期待どおりですが、デバッガーでステップスルーしたときと同じ奇妙な動作が発生します。私は自分のコードの根本的な問題が他の場所にあるのではないかと考え始めており、デバッガーの問題(またはおそらく出力の誤解)に転用されたばかりです。VisualStudioの「cdr[0]」、「cdr [1]」などの時計が、期待どおりに表示されない理由はわかっていますか?

#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"

#define NUM_REGIONS 50


void printArray(double *inVec, int len){
    int i;
    for(i=0; i<len; i++) printf("%f\t",inVec[i]);
    printf("\n");
}

int main(array<System::String ^> ^args){

    int numRatings = 25, remQuarters = 100, i, j, k;
    double ***cdr;
    char dummy;

    cdr = (double ***) malloc(NUM_REGIONS * sizeof(double **)); 
    for(i=0; i<NUM_REGIONS; i++){ 
        cdr[i] = (double **) malloc(numRatings * sizeof(double *)); 
        for(j=0; j<numRatings; j++){ 
            cdr[i][j] = (double *) malloc(remQuarters * sizeof(double)); 
        } 
    }

    for(i=0; i<NUM_REGIONS; i++){
        for(j=0; j<numRatings; j++){
            for(k=0; k<remQuarters; k++){
                cdr[i][j][k] = 100*i + 10*j +k;
            }
        }
    }

    for(i=0; i<5; i++) printf("%f\t",cdr[1][1][i]);
    printf("\n");
    for(i=0; i<5; i++) printf("%f\t",cdr[3][1][i]);
    printf("\n");
    for(i=0; i<5; i++) printf("%f\t",cdr[1][3][i]);
    printf("\n");
    for(i=0; i<5; i++) printf("%f\t",cdr[i][i][i]);
    printf("\n");
    printArray(cdr[1][1], 5);
    printArray(cdr[3][3], 5);

    scanf("%c", &dummy);
    return 0;
}

すべてのフィードバックに改めて感謝します。

4

5 に答える 5

6

ずっと前に大学で、Cの多次元配列は1D配列でエミュレートする必要があると結論付けました。まず、すべての要素を保持するのに十分な大きさのバッファを割り当てる必要があります。2D配列の場合はncolumns*nrows*sizeof(element)。次に、多次元インデックスを1Dインデックスに変換することにより、配列要素にアクセスします。2D配列の場合、A(i、j)にアクセスするとに変換されbufA[i*ncolumns+j]ます。

于 2010-07-26T19:31:46.273 に答える
1

問題は、間接参照にあります。cdr[i][j]あなたが望むことをしません。を割り当てるときはcdr[i]、そのインデックスにポインタを置きます。ただし、cdr[i][j]間接参照はしませんcdr[i]。長方形のメモリブロックがあることを前提とし、適切な値をcdrに追加して、どこにcdr[i][j]住んでいるかを判断します。おそらく、*sを使用して間接参照を手動で行う必要があります。

于 2010-07-26T20:00:18.817 に答える
1

私はあなたが見ている問題を正確に理解するのに苦労しました。

doubleの多次元配列に対して次のことを試しましたが、問題はありませんでした。

int i, j;
int rows = 5;
int columns = 10;
int z_axis = 5;
double ***cdr = malloc(rows * sizeof(double **));
for (i = 0; i < rows; i++)
{
  cdr[i] = malloc(columns * sizeof(double *));
  for (j = 0; j < columns; j++)
  {
    cdr[i][j] = malloc(z_axis * sizeof(double));
  }
}

この問題の詳細については、c-faqを参照してください:http://c-faq.com/aryptr/dynmuldimary.html

于 2010-07-26T19:30:53.227 に答える
0

何にcdrなっているの?doubleの3D配列(これは、スニペットに基づいて私が想定しているものです)?doubleへのポインタの2D配列?または、doubleの2D配列へのポインタ?

最初のものを想定して:

#include <stdlib.h>

int main(void)
{
  double ***cdr = malloc(sizeof *cdr * NUM_REGIONS);
  if (cdr)
  {
    size_t i;
    for (i = 0; i < NUM_REGIONS; i++)
    {
      cdr[i] = malloc(sizeof *cdr[i] * numRatings);
      if (cdr[i])
      {
        cdr[i][j] = malloc(sizeof *cdr[i][j] * remQuarters);
      }
    }
  }
  return 0;
}

注意すべきいくつかのこと:

  1. の戻り値をキャストしないでくださいmalloc()。C89の時点では、その必要はありません(voidポインターは暗黙的にターゲットポインター型に変換されます)。stdlib.hを含めるのを忘れた場合、またはスコープ内にプロトタイプがない場合malloc()、キャストは有用なものを抑制します。 「割り当てに互換性のないタイプ」の診断。
  2. sizeof型式ではなく、割り当てられるオブジェクトに対して演算子を使用します。これにより、ターゲットオブジェクトのタイプが変更された場合に保護されます。読みやすさにも役立つと思います。

これは機能するはずです。に相当するdoubleの3D配列が必要です

double cdr[NUM_REGIONS][numRatings][remQuarters];
于 2010-07-26T21:05:19.227 に答える
0

書かれたコードは機能したことがわかりました(ただし、何人かの人々が指摘したように、スタイルを改善する余地はありました)。コード内の実際の問題を、バッファーには大きすぎるファイル入力まで追跡しました(これはエラーチェックのレッスンです)。

デバッガーは、コードのこの部分に焦点を合わせた奇妙な出力を出しました。他の人がそうでないのに、なぜ私のデバッガーがこれを行っているのかはまだわかりませんが、別の日に対処します。

于 2010-07-27T14:17:22.043 に答える