我的理解是,指针可以用于动态分配内存,当你需要时(并且知道需要多少内存),而不是静态地使用数组预先分配内存。
我很难确定何时更好地节省计算时间来进行动态分配,以及何时拥有更大的内存占用空间并使用一些计算时间来仅分配所需的内存。
有人能在这个主题上提供一些见解吗?是否有任何通用规则可以帮助?
一般情况下,当您知道要处理的数据的总大小或者至少是一个最大数据大小时,您应该使用数组。特别是在数据大小变化不是非常大的情况下,例如变化在10到20项之间,最简单的方法可能就是分配20个项目并完成它(除非每个项目都非常大)。
如果您事先对数据的大小没有太多了解,或者(重要的可能性)可能很容易处理过多的数据无法计划放在堆栈上,则动态分配将变得更加有用。动态分配的主要弱点是,如果您需要知道大小,则需要自己跟踪它,并且您需要确保在完成后释放内存。许多C语言中(尤其是困难和令人讨厌的)问题归结为在释放内存后继续使用内存,或忘记在完成后释放内存。
在以下情况下应使用动态分配的内存:
在以下情况下应使用静态分配的内存:
使用动态分配的内存需要使用系统调用,这是当您的程序向操作系统请求某些内容时发生的。您会面临速度惩罚,因为该进程可能会失去分配给另一个进程的“处理时间”。操作系统需要执行许多任务才能完成调用。对于请求内存进行系统调用比仅写入存储在进程堆栈中的数组要复杂得多。
数组只是一段连续的内存块。当你声明一个数组时,你就拥有了一个指针。
int foo[5];
foo
(没有索引)是指向该数组中第一个元素的指针。
foo[0] = 1;
*foo = 1;
它们做相同的事情,如下所示:
foo[1] = 2;
*(foo + 1) = 2;
int foo[5];
创建一个数组时,你是在堆栈上创建的。这只限于当前函数,在从函数返回后就不再有效了。如果你使用malloc()
函数分配内存,那么你所创建的数组就在堆上(并且有一个指向它的指针)。int *foo = malloc(sizeof(int) * 5);
foo[0] = 1;
*foo = 1;
free()
释放它:free(foo);
void foo (int a[], int n) {
int buf[n];
/* do something with buf[] */
}
当你的数据是动态的,或者你需要从程序的不同区域传递数据时,你可以使用动态容器。
1 - 动态数据 比如说你有一个邻居列表。他们在你的街上建了一座新房子,你需要把一个人添加到列表中,但你只为15个邻居分配了足够的空间。这种动态内存可以让你增加容器的大小。实际上并不是这样工作的。它实际上是找到一个必要大小的新内存块,然后将旧容器复制过去。
再举个例子。假设你正在编写一个跟踪通讯录的程序。其中一个用户有十个联系人。另一个用户是一家公司,有五万名员工都需要存储在这个通讯录中。你不想为只有十个联系人的用户分配50000个空间,所以你只分配需要的空间。
2 - 传递数据 当你分配静态数据时,它被放在堆栈上,超出作用域后就无法访问。所以如果你调用某个生成数组的函数,并将数组的内存地址传递回给调用者,你会得到一个运行时错误。这是因为在该函数退出后,数组就超出了作用域,因此从堆栈中弹出。
然而,如果您动态分配它,它将进入堆栈,并且在您释放它或程序退出之前不会被释放。因此,您可以仅保留指向数组开头的指针,并在整个程序中使用它,而无需担心它超出范围,直到您想要释放它为止。