如何将数组的每个值作为参数传递给一个函数?

huangapple go评论103阅读模式
英文:

How to pass each value of an array as parameters to a function?

问题

我有以下接受可变数量整数参数并返回它们总和的函数。
```c
int sum(int a, ...){
    va_list nums;
    va_start(nums, a);
    int res=0;
    for(int i=0; i<a; i++) {
        res += va_arg(nums, int);
    }
    va_end(nums);
    return res;
}

我需要将数组的每个值作为参数传递给函数,而不是传递数组本身。数组的长度可以变化,导致要传递的参数长度也会变化。

printf("总和是:%d", sum(size, args[0], args[1], ```需要在此处使用args[]数组的所有元素```));

为了提供一些背景,我正在使用这个sum函数来理解如何做到这一点。知道如何在更一般的情况下实现这一点比在这个确切的函数中更有帮助。

如果你需要更多信息,请告诉我。

请参考这个类似的问题,然而,我需要在C语言中找到一个解决方案。

英文:

I have the following function that accepts a varying number of integer parameters and returns the sum.

int sum(int a, ...){
    va_list nums;
    va_start(nums, a);
    int res=0;
    for(int i=0; i<a; i++) {
        res += va_arg(nums, int);
    }
    va_end(nums);
    return res;
}

I need to pass each value of the array as a parameter to the function rather than passing the array itself. The array can be of varying length leading to a varying length of arguments to pass too.

printf("The sum is: %d", sum(size, args[0], args[1], ```need all elements of args[] array here```));

To put forth some perspective, I'm using this sum function to understand how I can go about doing this. It would be helpful to know how to achieve this in a more general setting rather than this exact function.

Please let me know if you need any more information.

Please do look at this question, which is similar, however, I require a solution in C.

答案1

得分: 4

简短回答是在C语言中没有直接实现这个功能的方法。C语言中没有类似ES6的扩展操作符,也没有类似的功能。我认为他们之所以没有实现这个功能并没有特别的原因(你只需将更多参数推送到堆栈上);他们只是从未创建过一个。

然而,有一些其他的事情你可以做:

  • 如果可变参数已经传递到调用你的函数的函数中,你可以将va_list传递给一个声明为接受va_list的函数。参见 链接

  • 正如@JonathanLeffer建议的,用C语言编写此代码的最自然方式是构建一个“将会是”你的可变参数的数组,并将其传递给一个期望一个数组(实际上是一个指针,因为数组会衰减为指针)的函数。例如:

    int sum_array(int a, int nums[]){
      int res=0;
      for(int i=0; i<a; i++) {
        res += nums[i];
      }
      return res;
    }
    
  • 在某些情况下,对于像sum_array这样的函数,它可能更方便只接受nums数组/指针,其中它本身会在最后一个槽中用0-1的值来表示数组的结束。这只是另一种用于指示结束的约定,由调用者设置。

  • 接着,如果你真的想要的话,可以编写一个将其参数收集到数组中并调用sum_array的可变参数函数,以便也有一个可变参数版本。当然,你也可以分别实现可变参数版本和数组版本,但对于复杂的函数来说,实现两次可能会很麻烦。

    int sum_variadic(int a, ...){
      va_list nums;
      va_start(nums, a);
      int arr[a];
      for(int i=0; i<a; i++) {
        arr[i] = va_arg(nums, int);
      }
      va_end(nums);
      return sum_array(a, arr);
    }
    
  • 你也可以使用宏来实现相同的目的:

    #define sum_macro(size, ...) sum_array(size, (int[]){__VA_ARGS__})
    

总结:在C中从可变参数到数组很容易,但从数组到可变参数是不可能的。

你也可以使用C语言的扩展来实现它,如 链接1链接2,@KamilCuk 提供了相关链接。

英文:

The short answer is that there's no way to do exactly this in the C language. There is no ES6-like spread operator in C, nor similar functionality. I don't think there's any particular reason why they couldn't (you would just have to push more arguments onto the stack); they just never made one.

However, there are various other things you can do:

  • If variadic arguments were already passed into the function calling your function, you can pass along the va_list to a function declared to take a va_list. See https://stackoverflow.com/questions/3530771/passing-variable-arguments-to-another-function-that-accepts-a-variable-argument

  • As @JonathanLeffer suggests, the most natural way to write this code in C is by constructing an array of what "would be" your variadic arguments, and passing that into a function that expects an array (well, technically, a pointer, because arrays decay to pointers). For example:

    int sum_array(int a, int nums[]){
      int res=0;
      for(int i=0; i&lt;a; i++) {
        res += nums[i];
      }
      return res;
    }
    
    • In certain circumstances, it may be more convenient for a function like sum_array to take only the nums array/pointer, which would itself indicate the end of the array with a 0 or -1 value in the last slot. This is just another convention for indicating the end, which the caller has to set up.
  • You could then, if you really wanted to, write a variadic function that collects its arguments into an array and calls sum_array, if you want a variadic version as well. (Of course, you could also just implement the variadic and array versions separately, but for nontrivial functions it may be a pain to implement them twice.)

    int sum_variadic(int a, ...){
      va_list nums;
      va_start(nums, a);
      int arr[a];
      for(int i=0; i&lt;a; i++) {
        arr[i] = va_arg(nums, int);
      }
      va_end(nums);
      return sum_array(a, arr);
    }
    
  • you could also use a variadic macro for the same purpose:

    #define sum_macro(size, ...) sum_array(size, (int[]){__VA_ARGS__})
    

In summary: going from variadic to array in C is trivial, going from array to variadic is impossible.

You can also use extensions to the C language to do it anyway, as described in https://stackoverflow.com/questions/50957748/passing-a-dynamic-set-of-variadic-arguments-to-a-c-function and https://stackoverflow.com/questions/12263745/in-c-given-a-variable-list-of-arguments-how-to-build-a-function-call-using-the, which @KamilCuk linked to.

答案2

得分: 2

您可以通过使用可变参数宏来避免显式传递参数的数量,而不是使用变参函数来构建复合字面量数组:

```c
#include <stdio.h>

#define sum_int(...)  (sum_int)(sizeof((int[]){__VA_ARGS__}) / sizeof(int), (int[]){__VA_ARGS__})

int (sum_int)(size_t count, const int *a) {
    int sum = 0;
    for (size_t i = 0; i < count; i++) {
        sum += a[i];
    }
    return sum;
}

int main() {
    printf("sum = %d\n", sum_int(1, 2, 3));
    return 0;
}

这种方法可以用于任何目的,只要可变参数的类型隐式转换为数组类型即可。

如果您想在不更改函数定义的情况下仅传递参数给您的 sum 函数,可以使用宏的变体:

#include <stdio.h>

int sum(int a, ...) {
    va_list nums;
    va_start(nums, a);
    int res = 0;
    for (int i = 0; i < a; i++) {
        res += va_arg(nums, int);
    }
    va_end(nums);
    return res;
}

#define sum(...)  (sum)((int)(sizeof((int[]){__VA_ARGS__}) / sizeof(int)), __VA_ARGS__)

int main() {
    printf("sum = %d\n", sum(1, 2, 3));
    return 0;
}

但需要注意的是,这种方法没有类型检查,sum(1, 2.0, 3) 将产生未定义行为。


<details>
<summary>英文:</summary>

You can avoid passing the number of arguments explicitly by using a variadic macro that constructs a compound literal array instead of a vararg function:

#include <stdio.h>

#define sum_int(...) (sum_int)(sizeof((int[]){VA_ARGS}) / sizeof(int), (int[]){VA_ARGS})

int (sum_int)(size_t count, const int *a) {
int sum = 0;
for (size_t i = 0; i < count; i++) {
sum += a[i];
}
return sum;
}

int main() {
printf("sum = %d\n", sum_int(1, 2, 3));
return 0;
}


This approach can be used for any purpose, as long as the types of the variable arguments are converted implicitly to the array type.

If you want to pass just the arguments to your `sum` function without changing its definition, you can use a variation of the macro:

#include <stdio.h>

int sum(int a, ...) {
va_list nums;
va_start(nums, a);
int res = 0;
for (int i = 0; i < a; i++) {
res += va_arg(nums, int);
}
va_end(nums);
return res;
}

#define sum(...) (sum)((int)(sizeof((int[]){VA_ARGS}) / sizeof(int)), VA_ARGS)

int main() {
printf("sum = %d\n", sum(1, 2, 3));
return 0;
}

Note however that there is no type checking with this approach and `sum(1, 2.0, 3)` would have undefined behavior.

</details>



huangapple
  • 本文由 发表于 2023年2月16日 13:45:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75468281.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定