我想从另一个数据结构在堆上创建一个结构数组。假设要遍历N个元素,并且(N-x)指针(computed_elements)将被添加到数组中。
我的天真策略是在堆栈上创建一个数组(temp_array)大小N并遍历数据结构,跟踪需要添加到数组中的元素数量,并在遇到它们时将它们添加到temp_array中。完成后,我使用malloc(computed_elements)并使用temp_array填充此数组。
这不是最理想的,因为第二个循环是不必要的。但是,我正在权衡这个与每次迭代不断重新分配内存的权衡。一些粗略的代码澄清:
void *temp_array[N];
int count = 0;
for (int i = 0; i < N; i++) {
if (check(arr[i])) {
temp_array[count] = arr[i];
count++;
}
}
void *results = malloc(count * sizeof(MyStruct));
for (int i = 0; i < count; i++) {
results[i] = temp_array[i];
}
return results;
我们将不胜感激。
答案 0 :(得分:3)
一个常见的策略是尝试估计您需要的元素数量(不是近似估计,更多是&#34;按... ...#34;类型估计的顺序) 。 Malloc那段记忆,当你得到&#34;关闭&#34;到了那个限度(&#34;关闭&#34;也正在进行解释),重新分配更多。就个人而言,当我接近填充它时,我通常会将数组加倍。
<强> - 编辑 - 强>
这是&#34;十分钟版本&#34;。 (我确保它构建并且不会发生段错误)
显然我省略了检查malloc / realloc成功,归零内存等事情......
#include <stdlib.h>
#include <stdbool.h>
#include <string.h> /* for the "malloc only version" (see below) */
/* Assume 500 elements estimated*/
#define ESTIMATED_NUMBER_OF_RECORDS 500
/* "MAX" number of elements that the original question seems to be bound by */
#define N 10000
/* Included only to allow for test compilation */
typedef struct
{
int foo;
int bar;
} MyStruct;
/* Included only to allow for test compilation */
MyStruct arr[N] = { 0 };
/* Included only to allow for test compilation */
bool check(MyStruct valueToCheck)
{
bool baz = true;
/* ... */
return baz;
}
int main (int argc, char** argv)
{
int idx = 0;
int actualRecordCount = 0;
int allocatedSize = 0;
MyStruct *tempPointer = NULL;
MyStruct *results = malloc(ESTIMATED_NUMBER_OF_RECORDS * sizeof(MyStruct));
allocatedSize = ESTIMATED_NUMBER_OF_RECORDS;
for (idx = 0; idx < N; idx++)
{
/* Ensure that we're not about to walk off the current array */
if (actualRecordCount == (allocatedSize))
{
allocatedSize *= 2;
/* "malloc only version"
* If you want to avoid realloc and just malloc everything...
*/
/*
tempPointer = malloc(allocatedSize);
memcpy(tempPointer, results, allocatedSize);
free(results);
results = tempPointer;
*/
/* Using realloc... */
tempPointer = realloc(results, allocatedSize);
results = tempPointer;
}
/* Check validity or original array element */
if (check(arr[idx]))
{
results[actualRecordCount] = arr[idx];
actualRecordCount++;
}
}
if (results != NULL)
{
free(results);
}
return 0;
}
答案 1 :(得分:0)
一种可能性是大小为N
的malloc,然后运行循环,然后重新分配大小N-x
。内存碎片可能导致小x。
答案 2 :(得分:0)
最佳可重用代码通常是可扩展。除非有义务使用小尺寸,否则假设代码将在后续应用程序中增长,并且对于大N需要合理有效。您确实希望重用良好的代码。
根据需要, realloc()
数组大约4倍。数组也可能缩小 - 不需要放置一个膨胀阵列。我使用了4倍的间隔1,4,16,64 ......并且收缩间隔为2,8,32,128 ......通过相互间隔生长/收缩间隔,它避免了大量的N应该在一段时间内动摇。
即使在很小的方面,例如使用size_t
与int
。当然,对于像1000这样的大小,没有区别,但是重复使用代码后,应用程序可能会突破限制:size_t
对于数组索引更好。
void *temp_array[N];
for (int i = 0; i < N; i++) {
void *temp_array[N];
for (size_t i = 0; i < N; i++) {