c函数返回两种可能的类型之一

时间:2018-12-30 13:38:05

标签: c function

我目前使用三种不同的函数来返回数值(一个返回一个double,另外两个返回一个long):

int main(void)
{
   // lots of code

    dRate = funcGetInterestRate();
    lMonths = funcGetTerm();
    lPrincipal = funcGetPrincipal();

    // lots of code

    return 0;
}

这三个函数代码大约有90%相同,因此我想合并为1个函数。我想将值标志传递给单个函数,如下所示:

  1. 如果传递了“ 1”,请确定利率,然后返回double
  2. 如果通过了“ 2”,请确定贷款期限,并返回long
  3. 如果通过了“ 3”,请确定贷款本金,并返回long

在调用函数时,我只想从该函数返回1个值,但是我想返回的值可以是doublelong。我想做这样的事情:

void funcFunction(value passed to determine either long or double)
{
   // lots of code

   if (foo)
      return double value;
   else
      return long value;
}

有一种简单的方法吗?

6 个答案:

答案 0 :(得分:10)

函数的返回类型在编译时是固定的。您无法根据传入的参数更改返回类型。

但是,由于您的主要目标是删除函数中的重复代码并将其合并,因此可以通过其他方式解决。换句话说,这是XY problem

在这种情况下,您可以做的是将三个函数中的每个函数的通用代码提取到一个单独的函数中,然后,三个原始函数可以调用该通用函数来完成大部分工作,然后提取所需的部分并返回。

例如:

struct loan {
    double rate;
    long term;
    long principal;
};

void calcLoan(struct loan *loan)
{
    // do stuff
    loan->rate = // some value        
    loan->term = // some value        
    loan->principal = // some value        
}

double funcGetInterestRate()
{
    struct loan loan;
    calcLoan(&loan);
    return loan.rate;
}

long funcGetTerm()
{
    struct loan loan;
    calcLoan(&loan);
    return loan.term;
}

long funcGetPrincipal()
{
    struct loan loan;
    calcLoan(&loan);
    return loan.principal;
}

答案 1 :(得分:1)

否,C不允许这样做。返回类型在函数声明中(您将其声明为void)。

稍微容易一点的是提供两个指向变量的指针,并指示在返回值中使用哪个指针:

int funcFunction(yourArgument, long *longResult, double *dblResult)
{
   // lots of code

   if (foo)
   {
      *dblResult = value;
      return 1;
   } else
   {
      *longResult = otherValue;
      return 0;
   }
}

(也许您甚至可以使用union。) 但是...我不得不在内部使用valueotherValue作为 函数,不能使用相同的变量来保存long 或< / em> double。同样,您可以使用union –但是这强调了只有一个功能到断点的渴望。

答案 2 :(得分:1)

您可以考虑返回一些tagged union。 Glib GVariant类型可能是鼓舞人心的,并且由于Glib是自由软件,因此您可以研究其源代码。另请参见this answer

因此,您将在内部声明一个带有匿名struct的公共union

struct choice_st {
   bool islong;
   union {
     long i; // valid when islong is true
     double d; // valid when islong is false
   }
}

,您可以返回该struct choice_st的值。

struct choice_st res;
if (foo) {
  res.islong = true;
  res.i = somelong;
  return res;
} 
else {
  res.islong = false;
  res.d = somedouble;
  return res;
}

您可能还决定使用C dynamic memory allocation,返回指向malloc的全新struct choice_st版指针,并采用约定由谁负责free-指针。 (顺便说一句,GVariant正在做类似的事情。)

答案 3 :(得分:0)

您可以做到这一点。显示起来比解释要容易,但是如果不清楚,我会添加一个解释:

void add_or_divide_by_xor(unsigned int a, unsigned int b, unsigned short c,
                          unsigned long *add, unsigned double *divide) {
    unsigned int xor = a ^ b;
    if (add != NULL) {
        *add = xor + c;
    }
    if (divide != NULL) {
        *divide = (double)xor / (double)c;
    }
}

致电:

unsigned long add;
unsigned double divide;
add_or_divide_by_xor(5, 17, 4, &add, NULL);
add_or_divide_by_xor(17, 6, 4, NULL, &divide);

答案 4 :(得分:0)

根据您的平台,double可能是long的超集。您应该已经知道这是否正确(因为您知道算法的作用以及它们可能的输出值是什么);如果您不这样做,请考虑以下事项:

  • double可以精确表示最多2个 53 的整数
  • long是32位或64位类型

因此,如果您的long值为32位,则始终可以从函数中返回double,并在需要时将其转换为函数外的long

答案 5 :(得分:0)

您可以尝试这样的事情。

#include <stdio.h>

void* func1(int key){
  static double interest;
  static long term;
  static long principle;

  //your common code to modify values of interest, term and principle
  //
  //Let us give them some dummy values for demonstration
  interest = 34.29347;
  term = 5843535;
  principle = 7397930;

  //conditions
  if(key == 1){
    return &interest;
  }
  else if(key == 2){
    return &term;
  }else if(key == 3){
    return &principle;
  }else printf("%s\n","error!!");
}

int main()
{
    printf("%f\n",*(double*)func1(1));
    printf("%ld\n",*(long*)func1(2));
    printf("%ld\n",*(long*)func1(3));
    func1(4);
    return 0;
}

输出

  

34.293470

     

5843535

     

7397930

     

错误!