动态分配数组解释

这是我的老师向我们展示的示例代码“如何在C中动态分配数组?”。 但我不完全理解这一点。 这是代码:

int k; int** test; printf("Enter a value for k: "); scanf("%d", &k); test = (int **)malloc(k * sizeof(int*)); for (i = 0; i < k; i++) { test[i] = (int*)malloc(k * sizeof(int)); //Initialize all the values } 

我想在C中,要定义一个数组,你必须把[]放在名字之后,那么究竟是什么是int** test ; 它不仅仅是一个指针指针吗? 而malloc()行也让我感到困惑…..

根据声明int** test;test是指向指针的指针 ,代码pice使用malloc函数动态地为int值矩阵分配内存。

声明:

 test = (int **)malloc(k * sizeof(int*)); // ^^------^^------- // allocate for k int* values 

k指针( int* )分配继续内存。 所以假设如果k = 4那么你会得到类似的东西:

  temp 343 347 351 355 +----+ +----+----+----+----+ |343 |---►| ? | ? | ? | ? | +----+ +----+----+----+----+ 

我假设地址是四个字节和? 意味着垃圾值。

temp分配了返回的地址,malloc分配了大小= k * sizeof(int**)继续内存块,在我的例子中是16个字节。

在for循环中,为k int分配内存,并将返回的地址分配给temp[i] (先前分配的数组的位置)。

 test[i] = (int*)malloc(k * sizeof(int)); //Initialize all the values // ^^-----^^---------- // allocate for k int values 

注意:表达式temp[i] == *(temp + i) 。 因此,在每次迭代中的for循环中,为k int值数组分配内存,如下所示:

  First malloc For loop --------------- ------------------ temp +-----+ | 343 |--+ +-----+ | ▼ 201 205 209 213 +--------+ +-----+-----+-----+-----+ 343 | |= *(temp + 0) | ? | ? | ? | ? | //for i = 0 |temp[0] |-------| +-----+-----+-----+-----+ | 201 | +-----------▲ +--------+ 502 506 510 514 | | +-----+-----+-----+-----+ 347 |temp[1] |= *(temp + 1) | ? | ? | ? | ? | //for i = 1 | 502 |-------| +-----+-----+-----+-----+ +--------+ +-----------▲ | | 43 48 52 56 351 | 43 | +-----+-----+-----+-----+ |temp[2] |= *(temp + 2) | ? | ? | ? | ? | //for i = 2 | |-------| +-----+-----+-----+-----+ +--------+ +-----------▲ 355 | | | 9002 | 9002 9006 9010 9014 |temp[3] | +-----+-----+-----+-----+ | |= *(temp + 3) | ? | ? | ? | ? | //for i = 3 +--------+ | +-----+-----+-----+-----+ +-----------▲ 

又一次? 意味着垃圾值。

附加要点:

1)您正在通过malloc转换返回的地址,但在C中您应该避免它。 读取我是否转换了malloc的结果? 只需按以下步骤操作:

 test = malloc(k* sizeof(int*)); for (i = 0; i < k; i++){ test[i] = malloc(k * sizeof(int)); } 

2)如果要动态分配内存,则需要在完成工作后明确释放内存(在释放动态分配的内存后,您无法访问该内存)。 释放内存进行test步骤如下:

 for (i = 0; i < k; i++){ free(test[i]); } free(test); 

3)如果你想为所有数组分配完全连续的内存,这是为2D矩阵分配内存作为数组的一种方法检查这个答案: 在函数C中分配内存2d数组

4)如果描述有帮助并且您想学习3D分配检查此答案: String of String或/ 3D char数组

请记住,数组衰减为指针,可以用作指针。 并且该指针可以用作数组。 事实上,索引数组可以看作是一个表单或指针算术。 例如

 int a[3] = { 1, 2, 3 }; /* Define and initialize an array */ printf("a[1] = %d\n", a[1]); /* Use array indexing */ printf("*(a + 1) = %d\n", *(a + 1)); /* Use pointer arithmetic */ 

上面的两个输出都将打印数组中的第二个(索引1 )项。

关于指针也是如此,它们可以与指针算法一起使用,或者与数组索引一起使用。

从上面可以看出,指针指向to.type是一个数组数组。 但这不是全部真相,因为它们在内存中的存储方式不同。 所以你不能将一个数组数组作为参数传递给一个需要一个指向指针的函数。 但是,在初始化之后,可以使用指向指针的指针,像正常指针一样使用数组索引。

malloc用于动态地将内存分配给测试变量,将*视为数组,将**视为数组数组,但不是通过值传递,指针用于引用变量的内存地址。 当调用malloc时,您通过获取整数的大小并乘以用户提供的int数来为测试变量分配内存,因为在用户输入之前不知道这一点。

是的,完全没问题。 test是指向指针的指针,所以test[i]相当于写test + i将是一个指针。 为了更好地理解,请查看此c – 常见问题解答 。

确实如此, int**是指向指针的指针。 我们也可以说它是一个指针数组。

 test = (int **) malloc(k * sizeof(int*)); 

这将首先分配一个k指针数组。 malloc动态分配内存。

 test[i] = (int*) malloc(k * sizeof(int)); 

这不是必需的,因为它足够了

 test[i] = (int*) malloc(sizeof(int*)); 

这里我们分配每个数组位置以指向有效的内存。 但是对于像int这样的基类型,这种分配没有意义。 它适用于较大的类型(结构)。

每个指针都可以像数组一样被访问,反之亦然,例如,以下是等效的。

 int a; test[i] = &a; (test + i) = &a; 

这可能是内存中的数组test ,从偏移0x10000000开始分配:

 + ------------ + ------------ +
 |  OFFSET | 指针|
 + ------------ + ------------ +
 |  0x10000000 |  0x20000000 | 试验[0]
 + ------------ + ------------ +
 |  0x10000004 |  0x30000000 | 试验[1]
 + ------------ + ------------ +
 |  ...... |  ...

每个元素(在此示例中为0x2000000和0x30000000)是指向另一个已分配内存的指针。

 + ------------ + ------------ +
 |  OFFSET | 价值|
 + ------------ + ------------ +
 |  0x20000000 |  0x00000001 |  *(test [0])= 1
 + ------------ + ------------ +
 |  ...
 + ------------ + ------------ +
 |  0x30000000 |  0x00000002 |  *(测试[1])= 2
 + ------------ + ------------ +
 |  ...

每个值仅包含sizeof(int)的空间。

在这个例子中, test[0][0]等价于*(test[0]) ,但是test[0][1]无效,因为它会访问未分配的内存。

对于每种类型T,存在类型“指向T的指针”。

可以通过* type声明符将变量声明为指向各种类型的值的指针。 要将变量声明为指针,请在其名称前面加上星号。

因此“对于每个类型T”也适用于指针类型,存在多个间接指针,如char **或int ***等。 还存在“指向数组的指针”类型,但它们不像“指针数组”那样常见( http://en.wikipedia.org/wiki/C_data_types

所以int** test声明一个指向“int数组”的指针数组

在行test = (int **)malloc(k*sizeof(int*)); 为k量( int* )提供足够的内存

所以有k个指针,每个都指向……

test[i] = (int*)malloc(k * sizeof(int)); (每个指针指向一个大小为k个int的数组)

摘要…

int** test; 由k个指针组成,每个指针指向k个量的int。

int **是指向int指针的指针。 看看“左右”规则