我已经编写了很长一段时间,但只是意识到我对一个非常基本的操作的混淆可能会混淆。
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 ++,有增强和嵌套向量,但它们甚至比上面更重,所以我会尽可能避免使用它们。
更新
老实说,我在这里要做的就是编译我的上面的例子,并对汇编器输出有所了解。那将很快回答我的所有问题。我的误解是我假设所有n-dim数组访问都是通过数学运算来完成的,类似于编译时已知数组的完成方式。我没有意识到[] []正在执行**array
的双重任务,并且在动态分配的每个取消引用之间进行适当的索引,而为编译时已知类型执行[i * dim + j]。动态2+维度阵列不是我曾经做过的事情。
答案 0 :(得分:5)
int **
和int[10][10]
类型不一样。
类型int **
不包含有关元素数量的任何信息,因为它不是数组类型,它是指针类型(特别是指向int *
的指针) 。 int[10][10]
包含编译器需要知道有多少元素的所有信息。
如果您尝试在指针与数组上使用sizeof
,则会注意到这一点。以下程序演示了这一点:
#include <stdio.h>
int main ( int argc, char * argv[] ) {
printf( "Size of int[10][10]: %lu\n", sizeof(int[10][10]) );
printf( "Size of int**: %lu\n", sizeof(int**) );
return 0;
}
动态内存在编译时没有分配,它是在运行时编译的,因此编译器改变动态内存的创建方式,最终可能会修改程序的行为,(IE。通过分配)比连续块中可用的更多,并且malloc返回null)。
当然,你可以通过为100 ints
分配足够的内存,然后自己做算术来获得连续的内存块:
int * mem = malloc( 10 * 10 * sizeof( int ) );
现在,mem是一个100个整数的连续块
int * array[10];
for ( int i = 0; i < 10; i++ )
array[i] = &mem[10*i];
现在你有一个10 int *
的数组,可用于索引到mem,就像之前一样(这个数组是静态分配的,但是如果你想从这个函数返回它你想要分配它是动态的。)
答案 1 :(得分:0)
因为类型完全不同。
在第一种情况下,具有两个维度的数组中的类型以及每个维度的长度是已知的,因此可以直接计算地址,并引用一次。
在第二种情况下,类型完全不同,类型是双指针。指向某种类型指针数组的指针,在您的情况下为int
。
编译器知道的所有内容是array
是指向某个未知大小的指向int
指针的数组的指针。 array
是
int **array;
array[x]
是指向int的指针。请注意,它只是指向int
的指针。它没有说明它指向的int
多少。
它可以只是一个int
,也可能不是。指向int
的每个指针都可以指向不同数量的int
。
例如,array [0]可能指向10个整数。 array [1]可能指向二十int
s。没有什么需要数组[x]指向与数组[y]相同数量的int
。
这份工作属于你,程序员。编译器不知道任何事情。您可以为每个这样的指针正确地将每个指针分配给int
到正确数量的int
s,然后将正确数量的指针分配给int
s首先。编译器不知道每个中有多少个,为了编写无错误的代码,以某种形式或方式跟踪它是你的工作。
欢迎使用C ++。