C程序中可变数量的参数

时间:2018-10-05 10:07:56

标签: c

每当我们使用C语言中的可变参数函数时,都必须提供参数总数作为第一个参数。有没有什么方法可以使函数具有可变的参数而不给出参数的总数?


[从comment更新:]

我想使用诸如sum(1,2,3)之类的函数应返回6,即那里不存在任何计数器。

5 个答案:

答案 0 :(得分:7)

几种方法:

  • 传递简单的显式计数(您在此问题中不需要)
  • 传递一些格式字符串,类似于printf和scanf
  • 传递一些“模式”参数,并让每个模式都需要特定的可变参数
  • 所有变量均属于同一类型,并且要求最后一个参数为某些特殊值,即AKA 前哨值,例如对于指针列表为NULL,对于整数类型则为该类型的max / min值,或NaN代表双打。

无论如何,您必须有某种方法让函数知道varargs的类型,以及知道它们何时结束的方法。 C中没有内置方法,参数计数不会传递给函数。

答案 1 :(得分:5)

  

我想使用诸如sum(1,2,3)之类的函数应返回6,即没有计数器存在

您可以定义一个哨兵。在这种情况下,@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_READ_CONTACTS: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted, yay! Do the // contacts-related task you need to do. } else { // permission denied, boo! Disable the // functionality that depends on this permission. } return; } // other 'case' lines to check for other // permissions this app might request. } } 可能有意义。

0

这样称呼它:

/* Sums up as many int as required. 
   Stops adding when seeing the 1st 0. */
int sum(int i, ...)
{
  int s = i;

  if (s)
  {
    va_list ap;

    va_start(ap, i); 

    /* Pull the next int from the parameter list and if it is
       equal 0 leave the while-loop: */
    while ((i = va_arg(ap, int))) 
    {
      s += i;
    }

    va_end(ap);
  }

  return s;
}

另外,int sum(int i, ...); int main(void) { int s = sum(0); /* Gives 0. */ s = sum(1, 2, 3, 0); /* Gives 6. */ s = sum(-2, -1, 1, 2, 0); /* Gives 0. */ s = sum(1, 2, 3, 0, 4, 5, 6); /* Gives 6. */ s = sum(42); /* Gives undefined behaviour! */ } 函数也可能看起来像这样(但会做一个无用加0的操作):

sum()

答案 2 :(得分:3)

您不必提供那么多参数。例如,考虑printf的签名:

int printf( const char* format, ... );

它通过解析您给它的字符串来“发现”它需要多少个参数。当然,您的函数需要以 some 的方式知道参数的数量,否则采用可变数量的参数对它有什么意义?

答案 3 :(得分:0)

可以创建一个以计数为第一个参数的可变参数函数,然后使用可变参数宏自动添加计数值:

#include <stdarg.h>

#define count_inner(a1, a2, a3, a4, a5, num, ...)  (num)
#define count(...)                                 count_inner(__VA_ARGS__, 5, 4, 3, 2, 1)
#define sum(...)                                   sum_func(count(__VA_ARGS__), __VA_ARGS__)

int sum_func(int count, ...)
{
    va_list ap;
    va_start(ap, count); 

    int total = 0;
    while(count--)
        total += va_arg(ap, int);

    va_end(ap);

    return total;
}

使用sum宏而不是sum_func可以省略计数,只要参数在1到5之间即可。可以根据需要将更多参数/数字添加到count_inner / count宏中。

int main(void)
{
    printf("%d\n", sum(1));
    printf("%d\n", sum(1, 2));
    printf("%d\n", sum(1, 2, 3));
    printf("%d\n", sum(1, 2, 3, 4));
}

输出:

1
3
6
10

答案 4 :(得分:0)

好吧,问题在于您必须在某种程度上向函数表明参数列表已用尽。您从printf(3)中获得了一个方法,即您可以在第一个参数(强制为字符串arg)中表示顺序和参数的类型,也可以在第一个参数中表示它。加,因为值0实际上并没有加到总和上,因此您可以使用该值(或其他根据您的标准)来表示最后一个参数。例如:

int sum(int a0, ...)
{
    int retval = a0;
    va_list p;
    va_start(p, a0);
    int nxt;
    while ((nxt = va_arg(p, int)) != 0) {
        retval += nxt;
    }
    return retval;
}

这样,您不必将参数数量作为第一个参数,您只需:

total = sum(1,2,3,4,5,6,7,8,9,10,0);

但是在这种情况下,您必须要小心,不要让中间参数等于零。或者,您也可以使用引用,您可以在引用不是NULL时添加,例如:

int sum(int *a0, ...)
{
    int retval = *a0;
    va_list p;
    va_start(p, a0);
    int *nxt;
    while ((nxt = va_arg(p, int*)) != NULL) {
        retval += *nxt;
    }
    return retval;
}

您可以:

int a, b, c, d, e, f;
...
int total = sum(&a, &b, &c, &d, &e, &f, NULL);
相关问题