C中的malloc()有哪些有用的例子?
我只是在C中阅读有关malloc()
的内容。
维基百科的文章提供了一个例子 ,但是与int array[10]
相比,它只为10个整数的数组分配了足够的内存。 不是很有用。
你何时决定使用malloc()
不是C为你处理内存?
动态数据结构(列表,树等)使用malloc
在堆上分配它们的节点。 例如:
/* A singly-linked list node, holding data and pointer to next node */ struct slnode_t { struct slnode_t* next; int data; }; typedef struct slnode_t slnode; /* Allocate a new node with the given data and next pointer */ slnode* sl_new_node(int data, slnode* next) { slnode* node = malloc(sizeof *node); node->data = data; node->next = next; return node; } /* Insert the given data at the front of the list specified by a ** pointer to the head node */ void sl_insert_front(slnode** head, int data) { slnode* node = sl_new_node(data, *head); *head = node; }
考虑如何使用sl_insert_front
将新数据添加到列表中。 您需要创建一个节点,该节点将保存数据和指向列表中下一个节点的指针。 你打算在哪里创造它?
- 也许在堆栈上! – 否 – 分配堆栈空间的位置? 在哪个function? 当函数退出时会发生什么?
- 也许在静态记忆! – 否 – 您必须事先知道您有多少列表节点,因为在程序加载时预先分配了静态内存。
- 在堆上? 是的 – 因为您拥有所有必需的灵活性。
malloc
在C中用于在堆上分配内容 – 内存空间可以在运行时动态增长和缩小,其所有权完全由程序员控制。 还有更多的例子,这是有用的,但我在这里展示的是一个代表性的例子。 最终,在复杂的C程序中,您会发现程序的大部分数据都在堆上,可通过指针访问。 正确的程序总是知道哪个指针“拥有”数据,并在不再需要时仔细清理已分配的内存。
如果在编写程序时不知道数组的大小怎么办? 举个例子,我们可以想象你想要加载一个图像。 首先你不知道它的大小,所以你必须从文件中读取大小,分配一个这个大小的缓冲区,然后读取该缓冲区中的文件。 显然你不能使用静态大小的数组。
编辑:
另一点是:当您使用动态分配时,将在堆上分配内存,而在堆上分配数组。 当您在嵌入式设备上进行编程时,这非常重要,因为与堆相比,堆栈的大小可能有限。
在您描述的示例中,当您离开堆栈帧时, int array[10]
会消失。 如果您希望使用的内存超出本地范围,则必须使用malloc();
我建议你谷歌堆栈和堆 。
int* heapArray = (int*)malloc(10 * sizeof(int)); int stackArray[10];
两者在访问数据的方式上非常相似。 它们在幕后存储数据的方式上有很大不同。 heapArray在堆上分配,仅在应用程序终止或调用free(heapArray)
时才被free(heapArray)
。 stackArray在堆栈上分配,并在堆栈展开时释放。
虽然从C99开始可以使用可变长度数组,但仍然没有更好的替代更动态的数据结构。 典型的例子是链表。 要获得任意大小,可以使用malloc
分配每个节点,以便在不进行大量内存复制的情况下插入和删除,就像使用可变长度数组一样。
例如,使用简单链表的任意大小的堆栈:
#include #include typedef struct sNode { int payLoad; struct sNode *next; } tNode; void stkPush (tNode **stk, int val) { tNode *newNode = malloc (sizeof (tNode)); if (newNode == NULL) return; newNode->payLoad = val; newNode->next = *stk; *stk = newNode; } int stkPop (tNode **stk) { tNode *oldNode; int val; if (*stk == NULL) return 0; oldNode = *stk; *stk = oldNode->next; val = oldNode->payLoad; free (oldNode); return val; } int main (void) { tNode *top = NULL; stkPush (&top, 42); printf ("%d\n", stkPop (&top)); return 0; }
现在, 可以使用可变长度数组来实现这一点,但是,就像在COBOL中编写操作系统一样,有更好的方法可以做到这一点。
malloc()用于:
-
您需要动态内存分配
如果需要创建大小为n的数组,其中n是在程序执行期间计算的,那么唯一的方法是使用malloc()。 -
您需要在堆中分配内存
某些函数中定义的变量仅在此函数结束时生效。 因此,如果需要一些“独立于callstack”的数据,它必须作为函数参数传递/返回(这并不总是合适的),或者存储在堆中。 在堆中存储数据的唯一方法是使用malloc()。 有可变大小的数组,但它们是在堆栈上分配的。