【问题标题】:How to return two values from a function? [duplicate]如何从函数中返回两个值? [复制]
【发布时间】:2011-07-16 11:26:54
【问题描述】:

可能重复:
returning multiple values from a function

假设我已将两个值传递给函数iCalculate(int x, int y),而此iCalculate 返回两个值。它们如下:-

  • (x*y)
  • (x/y)

现在我应该如何用同一个函数同时返回以上两个值?

我的方法是:-

int* iCalculate(int x,int y){
   int temp[2];
   temp[0] = x*y;
   temp[1] = x/y;
   return temp;
}

【问题讨论】:

  • 你有什么问题??

标签: c function


【解决方案1】:

返回本地数组的第一个元素的地址具有未定义的行为(至少稍后取消引用它是)。

你可以使用输出参数,即传递两个指针,并设置里面的值

void Calculate(int x, int y, int* prod, int* quot)
{
    *prod = x*y;
    *quot = x/y;
}

用法:

int x = 10,y = 2, prod, quot;
Calculate(x, y, &prod, &quot)

您可以做的另一件事是将数据打包到结构中

typedef struct 
{
    int prod;
    int quot;
} product_and_quot;


product_and_quot Calculate(int x, int y)
{
    product_and_quot p = {x*y, x/y};
    return p;
}

【讨论】:

  • 但对于 struct 的返回选项并不比我快。 C 程序员为什么总是首先想到指针解决方案,其次才是简单解决方案? ;)
  • 因为返回/传递结构意味着复制所有结构元素。这就是为什么我建议第三种解决方案:返回/传递指向结构的指针:-)
  • 返回一个本地数组然后在外部取消引用它最终肯定会失败,如果不是马上,堆栈爬升到足以破坏该数据只是时间问题。
  • @Dave:仅当您通过指针传递struct in 时,即让客户端负责分配它。让我们看看我们得到了什么:我们不再复制两个 32 位整数,而是只复制一个 32 位指针。它只需要一个额外的声明、一个& 运算符和两个取消引用。不,等等,32 位指针,那是在过去的硬件上......
  • @dragon135:增长struct 是一个有效的点,但对于这种数学函数,你知道会返回什么。
【解决方案2】:

这是行不通的,因为您要返回一个指向临时数组的指针,该指针将在函数返回时停止存在。

相反,定义

typedef struct { int first, second; } IntPair;

并返回该类型的对象。

(这是标准库函数divldiv 所做的,只是它们对类型的调用不同。)

【讨论】:

  • 是否有任何函数包含多个返回类型?
  • divldiv,最重要的是。大多数其他人通过指针返回,尽管这在现代机器上并不是真正需要的(它曾经是一种优化)。
【解决方案3】:

您的方法是错误的,temp 超出范围/在函数 iCalculate 退出时不再存在。所以一定不能返回temp的地址。那将是超出范围/不再存在变量的地址。访问该地址意味着未定义的行为。

您可以使用这种方法:

void iCalculate(int x,int y,int *mult,int *divi){
   *mult = x*y;
   *divi = x/y;
}

或者您可以使用其他方法:

typedef struct{ 
   int mul, divi;
} TResult;

TResult iCalculate(int x,int y){
   TResult res;
   res.mul = x*y;
   res.divi = x/y;
   return res;
}

或:

void iCalculate(int x,int y,TResult *res){
   res->mul = x*y;
   res->divi = x/y;
}

我建议第一种方法。我认为创建一个新的结构定义只是将两个不相关的值包装在一起太傻了。

【讨论】:

  • 不一定被破坏,但它会调用未定义的行为。众所周知,函数退出时堆栈不会填充零。抱歉,我只是有点悬念;)
  • 我只是在使用逻辑词。更正确的术语是变量超出范围。在 C 中没有任何东西被破坏,即使从堆中释放也不会用零填充它。
【解决方案4】:

你的做法是错误的,因为一旦函数返回,int temp[2] 就会消失,所以调用者有一个“悬空”指针。您必须添加static。另一种可能更好的方法是让调用者通过它想要存储结果的位置,例如

void iCalc(int x, int y, int *rp, int *rq)
{
   // check if rp and rq are NULL, if so, returns
   *rp = x*y;
   *rq = x/y; // y != 0, and this will truncate of course.
}

调用者会做类似的事情

int res[2];
iCalc(x, y, res, res+1);

或类似的。

【讨论】:

    【解决方案5】:

    您的方法并没有那么错误,您可以像这样返回表格的地址:

    int *iCalculate(int x,int y){
        int *temp=malloc(sizeof(int)*2);
        temp[0]=x*y;
        temp[1]=x/y;
        return temp;
    }
    

    别忘了释放内存:

    int *result;
    result=iCalculate(10,7);
    printf("%d %d\n",result[0],result[1]);
    free(result);
    

    【讨论】:

      猜你喜欢
      • 2016-05-07
      • 1970-01-01
      • 2011-04-18
      • 2020-12-03
      • 2019-11-05
      • 1970-01-01
      • 2010-09-30
      • 1970-01-01
      • 2012-04-02
      相关资源
      最近更新 更多