繁体   English   中英

从函数c返回多个值

[英]returning multiple values from function c

我来自c#,这给我带来了比我预期更多的问题。 我还没有看到直接的解决方案。 我是C语言的新手,只是玩弄它,而我尝试过的所有各种实现(从使用结构到传递指针)都无法完成工作。 (本地值不变)。 有人可以给我一个干练的例子吗?

这是我的代码示例

#include <stdio.h>

//alter values based on input
int * doStuff(int a, int b){
   int input;
   int arr[2]
   scanf("%d", &option);
   switch(option);
   case 1:
     arr[0] = a-2;
     arr[1] = b;
     return arr;
   break;
   case 2:
     arr[0] = a;
     arr[1] = b-2;
     return arr;
   break;
   default:
     return a, b;
}

main(){
   int a = 20;
   int b = 20;
   int returnedObject[2];
   //what i need is like in c# how I can do this
   returnedObject = doStuff(a, b);
    a = returnedObject[0];
   b= returnedObject[1];

}

我需要传递值,更改它们,返回它们并设置局部变量。 我完全迷失了一些更复杂的例子。 来自c#指针,数组,它们的工作方式让我迷失了,而且它没有我期望的那么简单。

C语言中的函数不能返回数组类型,数组也不能成为赋值的目标。 所以代码像

int returnedObject[2];
returnedObject = doStuff( a, b );

无法工作。 C函数可以返回指向数组的指针 ,但是我不认为您想要了解它。

C函数不能返回多个对象,也不支持多个分配。

如果两个值在逻辑上是某个较大的聚合类型的属性,则可以使用struct类型返回具有多个属性的单个对象,例如

struct result { int x, int y };

struct result doStuff( int a, int b )
{
  struct result ret = {a, b}; // initialize struct with inputs
  ...
  case 1:
    ret.x = a-2;
    break;  // y remains unchanged

  case 2:
    ret.y = b-2;
    break; // x remains unchanged
  ...
  return ret;
}

你称之为

struct result stuff;
stuff = doStuff( a, b );

或者,您可以将指针传递给您的值,并根据需要更新它们:

void doStuff( int *a, int *b )
{
  ...
  case 1:
    *a = *a - 2;
    break;

  case 2:
    *b = *b - 2;
    break;
}

你称之为

doStuff( &a, &b );

在这种情况下,您实际上不会向调用者返回任何内容。

您可以将数组作为参数传递给函数,如下所示:

void doStuff( int a, int b, int *result )
{
  result[0] = a; 
  result[1] = b;
  ...
  case 1:
    result[0] = a - 2;
    break;

  case 2:
    result[1] = b - 2;
    break;
  ...
}

你称之为

int results[2];
int a;
int b;
...
doStuff( a, b, results );

请注意,当我们将数组表达式传递给函数时,其类型从int [2]更改为int * 除非它是sizeof或一元&运算符的操作数,或者是用于初始化另一个数组的字符串文字,否则类型“ N的T元素数组”的表达式将被转换(“衰变”)为类型的表达式“指向T指针”,表达式的值将是数组第一个元素的地址。 C中的数组表达失去在大多数情况下,1他们的“阵性”。 您可以像使用数组表达式一样在指针表达式上使用下标运算符[] (数组索引操作a[i]定义为*(a + i) ),但是指针不是数组,反之亦然。


1.请注意,我在说的是表达式 ,而不是对象 数组对象始终是数组对象。

将返回类型设置为int *

创建一个局部变量int *result = malloc(sizeof(int) * 2); 然后将您的ab或任何您需要返回的result放入。

调用函数时,将结果分配给int *

int *res;
res = doStuff(a, b);
a = res[0];
b = res[1];

malloc为堆上的result分配空间。 它的输入是您需要的字节数。

2个int ,每个int 4个字节-> 8个字节== 2*sizeof(int)

问题在于,每次调用函数时,您将继续分配越来越多的空间。 C不会为您执行垃圾回收,因此当您使用int *res完成操作时,应通过调用free(res) 释放该空间。

更多详情:

在C#中,您将像这样初始化一个数组: int[] result = new result[2];

您是否都尝试过打印类似Console.WriteLine(myarray);的数组Console.WriteLine(myarray); 它行不通吗? C#我相信可以打印类似System.Int32[]东西。 如果您使用Java( System.out.println(myarray); )完成此操作,它将打印一些奇怪的数字。

该数字实际上是数组的地址。

当引用数组myarray ,实际上是在引用数组的地址。 当您执行诸如myarray[1] ,您将获取myarray的地址,并向其添加1*sizeof(int)并获取该值。

在C语言中,您可以按照典型的方式定义数组: int arr[2]; 分配2个整数的空间。

或者,您可以执行以下操作: int *arr; 它定义了一个指针(或地址)。 但是,您需要告诉它为整数分配空间。 到目前为止, arr并没有真正指向任何东西。 您可以通过调用malloc分配空间: arr = malloc(2*sizeof(int)); 动态分配2个整数的空间。

现在,您可以将内容放入数组中。 arr[0] = 1

[]有效地执行了指针算术。

arr[1] is the same as *(arr + 1)

arr + 1正在获取数组的地址并将其加1。 C看到您要添加一个int *因此它将1解释为1个int(4个字节)。 *运算符取消引用该地址,这意味着它跟随指针并获取存储在该地址的值。

如果打印arr给您0x1000arr+1给您0x1004*将返回存储在0x1004的int。

返回函数中的返回数组。

在C语言中,您无法像在C#中那样返回一个数组( int[] function(...) ),但是您可以返回一个指针( int *function(...) ),该指针可以像一个数组(参见上面的示例)。

您要使用malloc的原因是因为malloc在堆上分配了空间,因此您可以在函数返回后使用该数组。 如果您定义了类似int arr[2];的数组int arr[2]; ,该空间将在堆栈上分配,并且该函数返回后该数组将不会保留。

也许您应该看一下教程以了解有关指针的更多信息。 我认为我的回答太冗长,与问题不完全相关。

简单的解决方案(通过引用/指针传递允许更改存储的值)

#include <stdio.h>

//alter values based on input
void doStuff(int *a, int *b, int option)
{
    switch(option)
    {
        case 1:
            // a decremented by 2, b is unchanged
            *a = *a - 2;
            break;

        case 2:
            // b decremented by 2, a is unchanged
            *b = *b - 2;
            break;

        default:
            // a and b are unchanged
            break;
    }
}

int main()
{
    int a = 20;
    int b = 20;
    int option;

    printf("Enter option (1 or 2):\n");
    scanf("%d", &option);

    printf("BEFORE doStuff() :: a = %d, b = %d\n", a, b);
    doStuff(&a, &b, option);
    printf("AFTER doStuff() :: a = %d, b = %d\n", a, b);

    return 0;
}

您可以使用结构将数组包装起来以直接返回它。

#include <stdio.h>

struct doStuffRet {
   int arr[2];
};

//alter values based on input
struct doStuffRet doStuff(int a, int b){
   int option;
   struct doStuffRet r = {{a, b}};
   scanf("%d", &option);
   switch(option) {
      case 1:
         r.arr[0] = a-2;
         r.arr[1] = b;
         return r;
      break;
      case 2:
         r.arr[0] = a;
         r.arr[1] = b-2;
         return r;
      break;
      default:
         return r;
   }
}

int main(void){
   int a = 20;
   int b = 20;
   struct doStuffRet returnedObject;
   //what i need is like in c# how I can do this
   returnedObject = doStuff(a, b);
   a = returnedObject.arr[0];
   b = returnedObject.arr[1];
   printf("%d %d\n", a, b);
   return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM