2

我一直试图找出我在 C 中分配和使用多维动态分配数组的问题。我非常感谢任何帮助。

我尝试了两种方法。首先:

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));
   }
}  

第二个:

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] 等)都被设置为相同的值。随后的循环不会更改其中的任何一个。

我怀疑运算符优先级有问题,或者我取消引用错误,但我无法弄清楚。

谢谢。

更新

我将以下简化的代码放在一起,似乎可以正常工作。但是,虽然输出完全符合预期,但当我在调试器中单步执行时,我仍然会遇到同样奇怪的行为。我开始认为我的代码的根本问题可能在其他地方,而我刚刚被调试器的问题转移(或者可能只是因为我对输出的误解)。是否有已知原因导致 Visual Studio 中的“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 中的多维数组。第一个需要分配一个足够大的缓冲区来容纳所有元素。对于 2D 数组,它将是ncolumns*nrows*sizeof(element). 然后通过将多维索引转换为一维索引来访问数组元素。对于二维数组,访问 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

我很难弄清楚你到底看到了什么问题。

我为双精度的多维数组尝试了以下方法并且没有问题:

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?一个双精度的 3D 数组(这是我假设的,基于您的代码段)?指向双精度指针的二维数组?还是指向二维双精度数组的指针?

假设第一个:

#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 回答