为什么我的 C 多维动态分配不起作用?
我一直在试图解决我的分配问题以及在 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;
}
再次感谢您的所有反馈。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
很久以前,在大学里,我得出结论: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 tobufA[i*ncolumns+j]
.问题在于您的取消引用。
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 assigncdr[i]
, you're putting a pointer at that index. However,cdr[i][j]
doesn't dereferencecdr[i]
. It assumes you have a rectangular block of memory and adds the appropriate value to cdr to determine wherecdr[i][j]
lives. You're probably going to have to do the dereferencing manually with*
s.我很难弄清楚你到底遇到了什么问题。
我对双精度多维数组尝试了以下操作,没有出现任何问题:
有关此问题的具体信息,请参阅 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:
See the c-faq for specifics on this very issue: http://c-faq.com/aryptr/dynmuldimary.html
cdr
应该是什么?一个 3D 双精度数组(这是我根据你的代码片段假设的)?指向 double 的指针的二维数组?或者指向二维双精度数组的指针?假设第一个:
需要注意的一些事项:
malloc()
的返回值。从 C89 开始,您不需要(void 指针隐式转换为目标指针类型),并且如果您忘记包含 stdlib.h 或没有 malloc() 原型 在范围内,强制转换将抑制有用的“分配类型不兼容”诊断。sizeof
运算符,而不是类型表达式。这可以在目标对象的类型发生变化时为您提供保护;我认为它也有助于提高可读性。这应该有效;你应该有一个 3D 数组 double 相当于
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:
A few things to note:
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 formalloc()
in scope, the cast will suppress a useful "incompatible type for assignment" diagnostic.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
事实证明,编写的代码是有效的(尽管正如一些人指出的那样,它确实有风格改进的空间)。我将代码中的真正问题跟踪到一些对于缓冲区来说太大的文件输入(这对我来说是错误检查的一个教训)。
调试器给出了一些奇怪的输出,让我专注于这部分代码。我仍然不明白为什么我的调试器会这样做,而其他调试器却不会这样做,但我会在另一天处理这个问题。
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.