为什么我的 C 多维动态分配不起作用?

发布于 2024-09-12 05:01:54 字数 2467 浏览 8 评论 0 原文

我一直在试图解决我的分配问题以及在 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;
}

再次感谢您的所有反馈。

I have been trying to figure out the problem with my allocation and use of a multidimensional dynamically allocated array in C. I'd really appreciate any help.

I've tried two approaches. The first:

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

And the second:

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

Neither is working. In both cases, each cdr[i] ends up pointing to the same place. The first time I step into the 'i' loop, all cdr[i] (i.e. cdr[0], cdr[1], cdr[2], etc.) get set to the same value. Subsequent loops then don't change any of them.

I suspect there's something going on with operator precedence or I'm dereferencing wrong, but I haven't been able to figure it out.

Thanks.

UPDATE

I put together the following simplified code, which seems to work fine. But while the output is completely as expected, I'm still getting the same weird behaviour as I step through it in the debugger. I'm starting to think the fundamental problem with my code might be elsewhere, and I've just been diverted by issues with the debugger (or probably just with my misunderstanding of the output). Is there a known reason why a watch on 'cdr[0]', 'cdr[1]', etc. in Visual Studio wouldn't show what I'm expecting it to show?

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

Thanks again for all the feedback.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

篱下浅笙歌 2024-09-19 05:01:54

很久以前,在大学里,我得出结论:C 中的多维数组应该用一维数组来模拟。第一个需要分配一个足够大的缓冲区来容纳所有元素。对于二维数组,该数组为ncolumns*nrows*sizeof(element)。然后通过将多维索引转换为一维索引来访问数组元素。对于二维数组,访问 A(i,j) 会转换为 bufA[i*ncolumns+j]

A long time ago at college I concluded that multidimensional arrays in C should be emulated with 1D arrays. First one needs to allocate a buffer big enough to hold all of the elements. For a 2D array that would be ncolumns*nrows*sizeof(element). Then one accesses the array elements by transforming multidimensional indices to 1D index. For a 2D array, accessing A(i,j) translates to bufA[i*ncolumns+j].

瞎闹 2024-09-19 05:01:54

问题在于您的取消引用。 cdr[i][j] 不会做你想做的事。当您分配cdr[i]时,您将一个指针放在该索引处。但是,cdr[i][j] 不会取消引用 cdr[i]。它假设您有一个矩形内存块,并将适当的值添加到 cdr 以确定 cdr[i][j] 所在的位置。您可能必须使用 * 手动取消引用。

The problem is with your dereferencing. cdr[i][j] won't do what you want. When you assign cdr[i], you're putting a pointer at that index. However, cdr[i][j] doesn't dereference cdr[i]. It assumes you have a rectangular block of memory and adds the appropriate value to cdr to determine where cdr[i][j] lives. You're probably going to have to do the dereferencing manually with *s.

我做我的改变 2024-09-19 05:01:54

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

我对双精度多维数组尝试了以下操作,没有出现任何问题:

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

I had a tough time figuring out exactly what problem you are seeing.

I tried the following for a multidimensional array of doubles and had no problems:

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

See the c-faq for specifics on this very issue: http://c-faq.com/aryptr/dynmuldimary.html

护你周全 2024-09-19 05:01:54

cdr 应该是什么?一个 3D 双精度数组(这是我根据你的代码片段假设的)?指向 double 的指针的二维数组?或者指向二维双精度数组的指针?

假设第一个:

#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 运算符,而不是类型表达式。这可以在目标对象的类型发生变化时为您提供保护;我认为它也有助于提高可读性。

这应该有效;你应该有一个 3D 数组 double 相当于

double cdr[NUM_REGIONS][numRatings][remQuarters];

What is cdr supposed to be? A 3D array of double (which is what I'm assuming, based on your snippet)? A 2D array of pointer to double? Or a pointer to a 2D array of double?

Assuming the first:

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

A few things to note:

  1. Don't cast the return value of malloc(). As of C89, you don't need to (void pointers are implicitly converted to the target pointer type), and if you forget to include stdlib.h or otherwise don't have a prototype for malloc() in scope, the cast will suppress a useful "incompatible type for assignment" diagnostic.
  2. Use the sizeof operator on the object being allocated, not a type expression. This protects you in case the type of the target object changes; it also helps with readability, I think.

This should work; you should have a 3D array of double equivalent to

double cdr[NUM_REGIONS][numRatings][remQuarters];
静水深流 2024-09-19 05:01:54

事实证明,编写的代码是有效的(尽管正如一些人指出的那样,它确实有风格改进的空间)。我将代码中的真正问题跟踪到一些对于缓冲区来说太大的文件输入(这对我来说是错误检查的一个教训)。

调试器给出了一些奇怪的输出,让我专注于这部分代码。我仍然不明白为什么我的调试器会这样做,而其他调试器却不会这样做,但我会在另一天处理这个问题。

It turns out that the code as written worked (though it did have room for style improvements, as several people pointed out). I tracked the real problem in my code to some file input that was too big for the buffer (which is a lesson for me in error checking).

The debugger gave some weird output that had me focusing on this part of the code. I still don't understand why my debugger is doing this when others aren't, but I'll deal with that another day.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文