C语言 从函数返回多个值

kwvwclae  于 2023-01-04  发布在  其他
关注(0)|答案(2)|浏览(158)

在阅读this article之后,我理解了使用结构体或指针(前两种)返回多个值的方法,然而,在描述了第三种方法(使用临时数组)之后,作者写道:
我们不应该使用这种方法,因为变量信息不会传递给调用函数。例如,我们使用数组的索引来获取变量的值。另外,注意我们必须在堆中动态分配数组。如果我们使用静态数组,当我们退出函数时,它将不再存在,并且在调用函数内部访问它将导致未定义的行为。
这是作者提供的代码示例:

#include <stdio.h>
#include <stdlib.h>
 
// Function to return multiple values using an array
int* initialize()
{
    // Important: Dynamically allocate memory
    int *temp = (int*) malloc(sizeof(int) * 3);
 
    *temp = 10;
    *(temp + 1) = 20;
    *(temp + 2) = 30;
 
    return temp;
}
 
// Return multiple values from a function in C
int main(void)
{
    int a, b, c;
 
    int *arr = initialize();
 
    a = arr[0];
    b = arr[1];
    c = arr[2];
 
    printf("a = %d, b = %d, c = %d", a, b, c);
 
    // free memory
 
    return 0;
}

我不明白作者的意思,因为我在自己写的一个小程序中尝试过这个方法,看起来效果不错,也就是说,我可以在调用函数中访问返回数组的元素,为什么不推荐这样做呢?

6l7fqoea

6l7fqoea1#

引用的文本最好的情况是不清楚和混乱。最坏的情况是,完全错误。
我们不应该使用这种方法,因为变量信息不会传递给调用函数。
这里的"变量信息"是什么意思还不清楚。实际值返回给调用者,所以这不是问题所在。也许"变量信息"应该是指"关于变量数量的信息",但这并不清楚。
例如,我们使用数组的索引来检索变量的值。
是的,当然......如果这些值是在一个(动态分配的)数组中返回的,我们必须使用数组索引来获取它们。这是显而易见的,也不是真正的问题。
另外,请注意,我们必须在堆中动态分配数组。
终于有清楚正确的事了。
如果我们使用静态数组,当我们退出函数时,它就不再存在,并且在调用函数内部访问它将导致未定义的行为。
这里很不清楚"静态数组"指的是什么。代码中没有静态数组。它似乎指的是一些只在作者头中可用的代码...
如果作者考虑的代码是:

int temp[3];  // Instead of malloc

那么作者是正确的,但是...这不是一个静态数组。
如果作者考虑的代码是:

static int temp[3];  // Instead of malloc

那么作者是错误的。由于static,这个数组可以从调用者访问。
所以再次...非常困惑...
回答您的问题:
为什么不建议这样做?
嗯,有些担心可能是:
1.动态分配是一项开销很大的操作,所以除非有充分的理由,否则不要使用它。
1.从函数中返回动态分配的内存,并依赖调用方在以后释放它,这是许多内存泄漏错误的根源。因此,请避免这样做。

    • 但是**

好的实践规则几乎总是有例外的。
例如,假设一个函数返回了大量未知的结果,对于这样一个函数,返回一个指向动态分配内存的指针就可以了,但是你还需要返回结果的实际数量,如下所示:

int foo(int ** a)
{
    // Generate results and use code like
    *a = malloc(.. a lot ..)
    ...
    // Perhaps some realloc(.. even more ..)
    ...
    return number_of_results;  // or perhaps -1 on error
}

int * a;
int results = foo(&a);
if (results > 0)
{
    ....
    for (int i=0; i < results; ++i)
    {
         // Do something with a[i]
         ...
    }
    ....
    free(a);
}
...
r6vfmomb

r6vfmomb2#

如果我们使用静态数组,当我们退出函数时,它就不再存在,并且在调用函数内部访问它将导致未定义的行为。
垃圾,函数返回后static自动数组仍然存在,因为这样的数组有静态存储时间,函数就不是reentrant了。
作者可能指的是 * 自动存储持续时间 * 数组。
未定义行为(UB):

int *foo(void)
{
    int array[10];

    /* ... */ 
    return array;
}

无未定义行为:

int *bar(void)
{
    static int array[10];

    /* ... */ 
    return array;
}

相关问题