返回未知大小的C中的数组并使用终止值

时间:2016-02-01 13:54:28

标签: c arrays pointers

我是C新手,在处理未知大小的数组时遇到问题。

主要问题是我的函数my_func,比如说,有些工作并且需要输出一系列未知大小的值。即如果它是Java函数,它可能会返回一个ArrayList。

从谷歌搜索,似乎我最好的办法是做这样的事情:

MyStruct * myStructArr = (MyStruct *)malloc(MAX*sizeof(MyStruct));
my_func(myStructArr);

其中函数将使用适当的MyStruct值填充数组的项。选择MAX使其保证大于my_func的最大可能数组输出。

我对此有些不安,但我想这就是C中的工作原理。唯一剩下的问题是,在调用该函数后,我怎么知道已经设置了多少myStructArr个值?

似乎解决方案是做这样的事情:

`void my_func(MyStruct * myStructArr){
      //fill up the array (partially)

     // finally
     *myStructArr++ = SomeTerminatingItem;
}

此处SomeTerminatingItem表示数组的最后一项(其他项未初始化)。

所以在my_func之外,在调用之后我可以这样做:

while(*myStructArr != SomeTerminatingItem){
    // do whatever I want with the item.
    myStructArr++;
}

这是一种正确的方法吗?

4 个答案:

答案 0 :(得分:2)

返回从函数分配的内存是一个应该避免的微妙问题。您总是希望构建代码,以便在同一级别上分配和释放内存:

void* mem = malloc(N);
do_something(mem, N);
free(mem);

如果你事先完全不知道N,因为你正在阅读一个文件,你必须使用副作用来有效地返回两个值。

size_t my_func(void **mem) {
    size_t N = figure_out_N();
    *mem = malloc(N);
    return N;
}

用作:

void *mem;
size_t N = my_func(&mem);
do_something(mem, N);
free(mem);

使用终止值是一个坏主意,因为您必须排除它可能偶然出现在您的数据中的任何其他位置。如果需要,稍后计算出数组的大小也是低效的。

答案 1 :(得分:1)

查看链接列表,因为看起来您仍然会返回指向第一个项目的指针。此外,Java ArrayList的C等价物是链表。基本上,创建一个简单的节点结构:

struct node {
    MyStruct value;
    struct node *next;
};

*接下来应指向' next'列表中的项目。始终确保您不会丢失指向列表中第一项的指针。

答案 2 :(得分:1)

你有一个结构MyStruct。

我建议创建另一个结构MyStructArray,它包含一个元素计数和一个MyStruct *。这永远解决了将数组的大小保存在某处的问题,因为您需要的所有内容都包含在MyStructArray中。

答案 3 :(得分:1)

链接列表不等同于数组列表,它们是顺序访问,并且遍历需要遵循一系列指针。奇怪的是,我今天阅读了一篇SO帖子,其中包含了Java Arraylists的C实现的链接 - http://m-hewedy.blogspot.co.il/2010/09/java-like-arraylist-in-c.html

对于使用固定大小数组的开始实现很好,实际上甚至可以使用函数realloc(3)来扩展/缩小它 当他们真正需要时,有足够的时间来开发更多动态结构。例如,使用指向结构的指针表,分配&免费列表加快插入,删除&排序

定义将数组填充到最大元素的函数可能更好:

 unsigned my_fill_func(MyStruct myStructArr[], unsigned max) {
     unsigned count = 0;

     //fill up the array (partially)
     for ( ; count<max && fill_entry( &myStructArr[ count]);
         count++);

     // finally
     return count;
}