附带说明,ptr_one = (int *)malloc(sizeof(int)) 和 int *ptr_one = malloc(sizeof(int)) 之间有什么区别
见this。
首先,我知道这可能是一个荒谬的问题,因为动态内存分配是 C 编程中一个非常重要的话题。但是,我一直无法很好地解释这使我们能够做什么,或者为什么需要它。
与堆栈相比,内存池(或更常见的堆)非常大。考虑以下两个示例,了解为什么在堆栈上使用内存池很有用:
1. 如果您定义了一个数组并希望它在多个堆栈帧中持久存在,该怎么办?当然,您可以将其声明为全局变量,并将其存储在内存的全局数据部分中,但是随着程序变得越来越大,这将变得混乱。或者,您可以将其存储在内存池中。
int *func( int k ) {
assert( k >= 1 );
int *ptr_block = malloc( sizeof( int ) * k );
if ( ptr_block == NULL ) exit( EXIT_FAILURE );
for ( int i = 0; i < k; i++ ) {
ptr_block[ i ] = i + 1;
}
return ptr_block; // Valid.
}
... 但是,如果您在堆栈上定义了数组,这将 不 起作用。原因是,一旦弹出堆栈帧,所有内存地址都可以被另一个堆栈帧使用(并因此被覆盖),而使用内存池中的内存将持续到用户(您或客户端)freed。
2. 如果您想实现一个动态数组来处理读取任意大的数字序列怎么办?您将无法在堆栈上定义数组,您需要使用内存池。回想一下,将指针传递给结构,而不是结构本身(因为它们可能相当大),这是非常常见的(强烈推荐,除非您明确需要复制结构)。考虑这个动态数组的小实现:
struct dyn_array {
int *arr;
int len;
int cap;
};
typedef struct dyn_array *DynArray;
void insert_item( int const item, DynArray dyn_arr ) {
// Checks pre conditions.
assert( dyn_arr != NULL );
// Checks if the capacity is equal to the length. If so, double.
if ( dyn_arr->cap == dyn_arr->len ) {
dyn_arr->cap *= 2;
DynArray new_dyn_arr = malloc( sizeof( int ) * dyn_arr->cap ); // [oo]
// ... copy, switch pointers and free...
}
// ... insert, increase length, etc.
}
... 在[oo] 线上,请注意,如果这是在堆栈上定义的,那么一旦弹出此堆栈帧,将不再分配数组的所有内存地址。这意味着,另一个堆栈帧(可能是下一个)将使用这些内存地址(或其中的某个子集)。
备注: 从我的代码 sn-p 来看,ptr_block 存储在堆栈中:因此 &ptr_block 是堆栈地址,但 ptr_block 的值在内存中的某个位置游泳池。