如果我需要编写一个返回数组的函数:int *,哪种方式更好?
int* f(..data..)
或:void f(..data..,int** arr)
我们称之为:int* x; f(&x);
。 (也许它们都是相同的但我不确定。但是如果我还需要返回一个ErrorCode(它也是一个枚举),那么第一种方式f将获得ErrorCode *并且在第二种方式中,f将返回一个ErrorCode)。
答案 0 :(得分:5)
返回数组只是返回可变数量的数据 这是一个非常古老的问题,C程序员为此开发了许多答案:
strcpy()
strcpy_s()
{}} getline()
snprintf()
fread()
gets()
。这是一个设计缺陷,因此在较新版本中不推荐使用该功能,为了完整性,此处仅提及:qsort_s()
。qsort()
fopen()
:fclose()
- > strdup()
free()
- > asctime()
请注意,返回的数组必须包含sentinel对象或其他标记,您必须单独返回长度,或者必须返回包含指向数据和长度的指针的结构。
传递引用(指向大小等)可以帮助那里。
通常,每当用户必须猜测尺寸或在手册中查找时,他有时会弄错。如果他没有弄错,后来的修改可能会使他的细心工作无效,所以他曾经是对的并不重要。无论如何,这种方式是errno
。
对于其他人,请选择最舒适,最有效的方式。
关于错误代码:请记住{{3}}。
答案 1 :(得分:1)
通常返回数组
更方便和语义int* f(..data..)
如果您需要复杂的错误处理(例如,返回错误值),您应该将错误返回为int,并将数组返回值。
答案 2 :(得分:1)
没有更好的"在这里:您决定哪种方法更适合呼叫者的需求。
请注意,这两个函数都必须为用户提供一个内部分配的数组,因此取消分配结果数组将成为调用者的责任。换句话说,在f()
内的某个位置,您将拥有malloc
,并且接收数据的用户必须在其上调用free()
。
你还有另一个选择 - 让调用者将数组传递给你,然后返回一个数字,说明你放回了多少项:
size_t f(int *buffer, size_t max_length)
这种方法允许调用者在静态或自动内存中传递缓冲区,从而提高灵活性。
答案 3 :(得分:1)
经典模型是(假设您还需要返回错误代码)
int f(...., int **arr)
即使它不像返回数组的函数那样流动
请注意,这就是为什么可爱的go语言支持多个返回值。
它也是异常的原因之一 - 它从函数i / o空间中获取错误指标
答案 4 :(得分:1)
如果不需要处理函数中已存在的指针,则第一个更好。 当你已经有一个指向已经分配的容器的定义指针(例如一个列表)并且在函数内部可以改变指针的值时,就会使用第二个。
答案 5 :(得分:0)
如果您必须像f
那样致电int* x; f(&x);
,那么您没有太多选择。您必须使用第二种语法,即void f(..data..,int** arr)
。这是因为您在代码中没有使用返回值。
答案 6 :(得分:0)
该方法取决于具体任务,也可能取决于您的个人品味或项目中采用的编码惯例。
一般情况下,出于多种原因,我想将指针作为“输出”参数而不是return
传递给数组。
您可能希望将数组中的多个元素与数组本身一起返回。但如果你这样做:
int f(const void* data, int** out_array);
然后,如果你第一次看到签名,你就不能完全知道函数返回的内容,元素的数量或错误代码,所以我更喜欢这样做:
void f(const void* data, int** out_array, int* out_array_nelements);
甚至更好:
void f(const void* data, int** out_array, size_t* out_array_nelements);
函数签名必须是不言自明的,参数名称有助于实现这一点。
输出数组需要存储在某处。您需要为阵列分配一些内存。如果return
指向数组的指针而不传递与参数相同的指针,那么不能在堆栈上分配内存。我的意思是,你不能这样做:
int f (const void *data) {
int array[10];
return array; /* the array is likely deallocated when the function exits */
}
相反,您必须执行static int array[10]
(这不是线程安全的)或int *array = malloc(...)
,这会导致内存泄漏。
所以我建议你传递一个指向函数调用之前已经分配的数组的指针,如下所示:
void f(const void *data, int* out_array, size_t* out_nelements, size_t max_nelements);
好处是您可以自由选择分配阵列的位置:
在堆栈上:
int array[10] = { 0 };
size_t max_nelements = sizeof(array)/sizeof(array[0]);
size_t nelements = 0;
f(data, array, &nelements, max_nelements);
或者在堆中:
size_t nelements = 0;
size_t max_nelements = 10;
int *array = malloc(max_nelements * sizeof(int));
f(data, array, &nelements, max_nelements);
通过这种方法,您可以自由选择如何分配内存。