【发布时间】:2015-06-18 00:00:31
【问题描述】:
我已经编写了很长时间的代码,但刚刚意识到我对一个非常基本的操作的交互可能会感到困惑。
int array[10][10];
array[1][1] = 0;
这是足够的样本 - 数组地址 + (10 * 1 + 1) * sizeof(int) 分配为 0。
但是在做动态数组的时候呢?
int **array;
// malloc/new the base array of pointers - say 10 as above.
array = malloc(10 * sizeof(int *));
// through pointers and alloc each with ints - again 10 per row as above.
for(int i=0; i<10; i++)
array[i] = malloc(10 * sizeof(int);
array[1][1] = 0;
在这个例子中,编译器必须在数组的第一层引用一个数组来获取第二个指针以获取内存。同样,这个过程很简单。
我的问题是:编译器如何知道内存是连续的,因此它可以只做简单的数学运算而不是第一个示例中的引用,而不是第二个示例?
如果答案是:因为编译器事先知道数组的大小,就这样吧,但是有没有办法告诉编译器动态数组是一个单一的分配,因此它可以做更简单的数学运算而不是额外的 deref 和额外的内存碎片分配?或者这是否需要 VLA 支持才能按照this post 正确处理,如下所示:
double (*A)[n] = malloc(sizeof(double[n][n]));
另一个网站也列出了这种可能性:
int r=3, c=4;
int **arr;
arr = (int **)malloc(sizeof(int *) * r);
arr[0] = (int *)malloc(sizeof(int) * c * r);
这真的让我想知道编译器是如何解决问题的,或者这是否只是使用 VLA 支持的另一种方式。
对于 C++,有 boost 和嵌套向量,但它们比上面的还要重,所以如果可能的话,我会避免使用这些。
更新
老实说,我在这里应该做的只是编译我上面的例子,然后看看汇编器的输出。这将很快回答我所有的问题。我的误解是,我假设所有 n-dim 数组访问都是通过类似于编译时已知数组的数学运算完成的。我没有意识到 [][] 作为**array 正在执行双重职责,在动态分配的每个取消引用之间进行适当的索引,同时对编译时已知类型执行 [i*dim+j]。动态 2+ 维数组不是我必须做的事情。
【问题讨论】:
-
一个词:types。这就是我们有类型的原因。特别注意
int**与int[10][10]的不同之处,后者不能 衰减为前者(它会衰减为int(*)[10]或类似的东西)。我不真的明白你在问什么,因为你的整个问题(根据定义)是基于一个基本的误解。不幸的是,我们还不确切地知道这种误解是什么。 :) 这可能会在聊天室中得到更好的解决。