为什么需要为越来越多的指针数组重新分配内存?
Why is it desirable to realloc() memory for a growing array of pointers?
typedef struct {
void **head;
size_t used_size;
size_t free_size;
size_t current_size;
size_t size_increment;
} GrowingArray;
GrowingArray createEmptyGrowingArray(int initial_size, int size_increment) {
GrowingArray empty_growing_array;
empty_growing_array.head = malloc(initial_size * sizeof(void *));
empty_growing_array.used_size = 0;
empty_growing_array.free_size = initial_size;
empty_growing_array.current_size = initial_size;
empty_growing_array.size_increment = size_increment;
return empty_growing_array;
}
GrowingArray appendToGrowingArray(GrowingArray growing_array, void *new_element) {
void *new_head_of_array;
if (growing_array.free_size == 0) {
new_head_of_array = realloc(growing_array.head, (growing_array.current_size + growing_array.size_increment) * sizeof(void*));
if (new_head_of_array == NULL) {
printf("Reallocation failure.\n");
}
growing_array.free_size = growing_array.size_increment;
growing_array.current_size += growing_array.size_increment;
growing_array.head = new_head_of_array;
}
growing_array.head[growing_array.used_size++] = new_element;
growing_array.free_size--;
return growing_array;
}
void finalizeGrowingArrayMemory(GrowingArray growing_array) {
growing_array.head = realloc(growing_array.head, growing_array.current_size * sizeof(void *));
}
void freeGrowingArray(GrowingArray growing_array) {
free(growing_array.head);
}
int main(int argc, char* argv[]) {
GrowingArray test_array = createEmptyGrowingArray(5, 1);
int *test_integer = (int *)malloc(1 * sizeof(int));
*test_integer = 4;
int *another_integer = (int *)malloc(1 * sizeof(int));
*another_integer = 6;
int *yet_another_integer = (int *)malloc(sizeof(int));
*yet_another_integer = 9;
test_array = appendToGrowingArray(test_array, test_integer);
test_array = appendToGrowingArray(test_array, another_integer);
test_array = appendToGrowingArray(test_array, yet_another_integer);
finalizeGrowingArrayMemory(test_array);
printf("%x,", *(int *)test_array.head[0]);
printf("%x,", *(int *)test_array.head[1]);
printf("%x\n", *(int *)test_array.head[2]);
freeGrowingArray(test_array);
printf("Going to free %llx\n", (long long int)test_integer);
free(test_integer);
printf("Going to free %llx\n", (long long int)another_integer);
free(another_integer);
printf("Going to free %llx\n", (long long int)yet_another_integer);
free(yet_another_integer);
return 0;
}
我根据这个问题的正确答案中提供的示例代码编写了这段代码:
提供的答案包括一个简单地重新分配指针数组的函数。预期用途是在将多个项目附加到数组后调用它,如答案代码所示。
我想知道为什么要这样做。它有什么好处? realloc() 是否尝试根据之前的使用情况预测一块内存将如何使用,然后将其移动到它认为最好的地方?
谢谢!
作为附加的是或否问题:我应该在 createEmptyGrowingArray()
中使用 calloc()
而不是 malloc()
吗?
I want to know why this should be done. What benefit does it provide?
我想你是在问为什么它有一个功能,或者为什么有一个可配置的增量:
- 将重新分配的细节分离到自己的区域以避免代码混乱,并且提供可从您可能实施的其他形式的 "insert" 调用中调用的可重用的调整大小操作很方便.
- 增量配置允许您将数组扩大一个以上的元素,从而防止过多的重新分配。
- 虽然您的示例没有这样做,但增加增量大小也很有用。这将允许 constant amortized time complexity 用于数组增长。
Does realloc() try to make predictions about how a block of memory is going to be used based on its prior usage and then move it where it thinks is best?
不,它不知道你的块是用来做什么的。它只是分配一块内存。如果它可以在不移动内存的情况下调整它的大小,它会的。但是如果 space 不够用,或者必须移动到不同的分配方案(内存管理器经常根据块的大小将块分成不同的区域),那么指针就会移动,那块内存的内容就会复制到新位置。
As an add-on yes or no question: Should I be using calloc() instead of malloc() inside createEmptyGrowingArray()?
使用 calloc
是合理的做法,但是当您创建一个空数组时,请记住您将当前大小设置为零,所以 malloc
就足够了,因为您不会使用那些未初始化的值,直到您稍后初始化它们(追加之后)。此外,在调用 realloc
来增加块后,您当前并未将新内存中的指针归零,因此它不提供与您的 "create" 操作的概念奇偶校验。
因此,在您的情况下,我建议使用 malloc
,这不会对您未使用的数据的状态给出不切实际的期望。如果你想在创建时使用calloc
,那么你也应该在增长后使用memset
将新内存清零。
typedef struct {
void **head;
size_t used_size;
size_t free_size;
size_t current_size;
size_t size_increment;
} GrowingArray;
GrowingArray createEmptyGrowingArray(int initial_size, int size_increment) {
GrowingArray empty_growing_array;
empty_growing_array.head = malloc(initial_size * sizeof(void *));
empty_growing_array.used_size = 0;
empty_growing_array.free_size = initial_size;
empty_growing_array.current_size = initial_size;
empty_growing_array.size_increment = size_increment;
return empty_growing_array;
}
GrowingArray appendToGrowingArray(GrowingArray growing_array, void *new_element) {
void *new_head_of_array;
if (growing_array.free_size == 0) {
new_head_of_array = realloc(growing_array.head, (growing_array.current_size + growing_array.size_increment) * sizeof(void*));
if (new_head_of_array == NULL) {
printf("Reallocation failure.\n");
}
growing_array.free_size = growing_array.size_increment;
growing_array.current_size += growing_array.size_increment;
growing_array.head = new_head_of_array;
}
growing_array.head[growing_array.used_size++] = new_element;
growing_array.free_size--;
return growing_array;
}
void finalizeGrowingArrayMemory(GrowingArray growing_array) {
growing_array.head = realloc(growing_array.head, growing_array.current_size * sizeof(void *));
}
void freeGrowingArray(GrowingArray growing_array) {
free(growing_array.head);
}
int main(int argc, char* argv[]) {
GrowingArray test_array = createEmptyGrowingArray(5, 1);
int *test_integer = (int *)malloc(1 * sizeof(int));
*test_integer = 4;
int *another_integer = (int *)malloc(1 * sizeof(int));
*another_integer = 6;
int *yet_another_integer = (int *)malloc(sizeof(int));
*yet_another_integer = 9;
test_array = appendToGrowingArray(test_array, test_integer);
test_array = appendToGrowingArray(test_array, another_integer);
test_array = appendToGrowingArray(test_array, yet_another_integer);
finalizeGrowingArrayMemory(test_array);
printf("%x,", *(int *)test_array.head[0]);
printf("%x,", *(int *)test_array.head[1]);
printf("%x\n", *(int *)test_array.head[2]);
freeGrowingArray(test_array);
printf("Going to free %llx\n", (long long int)test_integer);
free(test_integer);
printf("Going to free %llx\n", (long long int)another_integer);
free(another_integer);
printf("Going to free %llx\n", (long long int)yet_another_integer);
free(yet_another_integer);
return 0;
}
我根据这个问题的正确答案中提供的示例代码编写了这段代码:
提供的答案包括一个简单地重新分配指针数组的函数。预期用途是在将多个项目附加到数组后调用它,如答案代码所示。
我想知道为什么要这样做。它有什么好处? realloc() 是否尝试根据之前的使用情况预测一块内存将如何使用,然后将其移动到它认为最好的地方?
谢谢!
作为附加的是或否问题:我应该在 createEmptyGrowingArray()
中使用 calloc()
而不是 malloc()
吗?
I want to know why this should be done. What benefit does it provide?
我想你是在问为什么它有一个功能,或者为什么有一个可配置的增量:
- 将重新分配的细节分离到自己的区域以避免代码混乱,并且提供可从您可能实施的其他形式的 "insert" 调用中调用的可重用的调整大小操作很方便.
- 增量配置允许您将数组扩大一个以上的元素,从而防止过多的重新分配。
- 虽然您的示例没有这样做,但增加增量大小也很有用。这将允许 constant amortized time complexity 用于数组增长。
Does realloc() try to make predictions about how a block of memory is going to be used based on its prior usage and then move it where it thinks is best?
不,它不知道你的块是用来做什么的。它只是分配一块内存。如果它可以在不移动内存的情况下调整它的大小,它会的。但是如果 space 不够用,或者必须移动到不同的分配方案(内存管理器经常根据块的大小将块分成不同的区域),那么指针就会移动,那块内存的内容就会复制到新位置。
As an add-on yes or no question: Should I be using calloc() instead of malloc() inside createEmptyGrowingArray()?
使用 calloc
是合理的做法,但是当您创建一个空数组时,请记住您将当前大小设置为零,所以 malloc
就足够了,因为您不会使用那些未初始化的值,直到您稍后初始化它们(追加之后)。此外,在调用 realloc
来增加块后,您当前并未将新内存中的指针归零,因此它不提供与您的 "create" 操作的概念奇偶校验。
因此,在您的情况下,我建议使用 malloc
,这不会对您未使用的数据的状态给出不切实际的期望。如果你想在创建时使用calloc
,那么你也应该在增长后使用memset
将新内存清零。