C函数是否支持任意数量的参数?

4

PHP有一个func_get_args()函数用于获取所有函数参数,而JavaScript则有functions对象。

我已经在C中编写了一个非常简单的max()函数。

int max(int a, int b) {
    
    if (a > b) {
        return a;   
    } else {
        return b;
    }
}

我相信在大多数语言中,您可以向其max()(或等效)内置函数提供任意数量的参数。在C中是否也可以这样做?

我认为这个问题可能是我想要的,但我不认为它是。

请记住我也还在学习。 :)

非常感谢。

7个回答

11
你可以编写一个可变参数的函数,该函数接受参数数量,例如:
#include <stdio.h>
#include <stdarg.h>

int sum(int numArgs, ...)
{
    va_list args;
    va_start(args, numArgs);

    int ret = 0;

    for(unsigned int i = 0; i < numArgs; ++i)
    {
        ret += va_arg(args, int);
    }    

    va_end(args);

    return ret;
}    

int main()
{
    printf("%d\n", sum(4,  1,3,3,7)); /* prints 14 */
}
该函数假设每个可变参数都是整数(请参见va_arg调用)。

6
这是一个相当奇怪的 max 实现方式... ;) - Dummy00001
1
谢谢,但 max() 的作用是返回最大的数字,而不是将它们相加 :P - alex
1
我必须告诉函数我发送了多少个参数吗?printf()似乎不需要知道,但我猜它可以通过计算第一个参数中的所有格式字符来找出。 - alex
1
@alex:是的,你必须这样做。但是你可以使用宏来解决这个问题。例如,可以使用一个哨兵值INT_MIN来停止函数遍历参数。然后,你可以定义一个可变参数宏(注意,并非所有编译器都支持)#define max(...) maxfunction(__VA_ARGS__, INT_MIN) - AndiDog
1
@AndiDog:我期望 max(INT_MIN, 0) 是被定义好的。我真的看不出如何安全地传递一个哨兵。 - MSalters
显示剩余3条评论

5

是的,C语言有可变参数函数的概念,类似于printf()允许使用可变数量的参数。

一个求最大值的函数可能如下所示:

#include <stdio.h>
#include <stdarg.h>
#include <limits.h>

static int myMax (int quant, ...) {
    va_list vlst;
    int i;
    int num;
    int max = INT_MIN;

    va_start (vlst, quant);

    for (i = 0; i < quant; i++) {
        if (i == 0) {
            max = va_arg (vlst, int);
        } else {
            num = va_arg (vlst, int);
            if (num > max) {
                max = num;
            }
        }
    }
    va_end (vlst);
    return max;
}

int main (void) {
    printf ("Maximum is %d\n", myMax (5, 97, 5, 22, 5, 6));
    printf ("Maximum is %d\n", myMax (0));
    return 0;
}

这将输出:
Maximum is 97
Maximum is -2147483648

请注意quant变量的使用。通常有两种方法来指示您的参数结束,一种是提前计数(即5),另一种是在末尾使用哨兵值。
后者的一个例子是指针列表,将NULL作为最后一个传递。由于这个max函数需要能够处理整个整数范围,因此哨兵解决方案不可行。 printf函数使用前面的方法,但略有不同。它没有特定的计数,而是使用格式字符串中的%字段来确定其他参数。

3
事实上,这是两个问题。首先,C99只要求C实现至少可以处理以下内容:
  • 一个函数定义中的127个参数
  • 一个函数调用中的127个参数
现在,回答你的真正问题,是的,C99中有所谓的可变参数函数和宏。声明的语法在参数列表中使用...。可变参数函数的实现需要使用stdarg.h头文件中的宏。

2

这里有一个链接,展示了在C语言中使用可变参数的示例:编写“varargs”函数

你可以使用va_args函数来检索传递给函数的可选参数。通过这种方式,你可以传递0-n个可选参数。因此,如果需要,你可以支持更多的参数。


2
请注意,与PHP和Javascript不同,使用C语言的varargs时,您的函数需要能够从非变量参数的值中确定varargs的类型和数量(或者我猜您可以从非变量参数中确定第一个可变参数的类型,然后从第一个值的类型确定第二个参数的类型,以此类推)。因此,您将无法获得预期中的可变参数“max”函数 - 这是C语言的限制。 - Steve Jessop
@Steve:你可以通过使用可变宏包装可变参数函数来解决这个问题,该宏会计算参数数量并将其作为第一个参数传递。 :-) - R.. GitHub STOP HELPING ICE

1
是的,你可以在C语言中声明一个可变参数函数。最常用的可能是printf,它的声明看起来像下面这样。
int printf(const char *format, ...);

...是如何声明接受可变数量参数的。

要访问这些参数,可以使用va_startva_arg等通常在stdarg.h中定义的宏。请参见此处

值得注意的是,您经常可以“混淆”这样的函数。例如,对printf的以下调用将打印在调用时在堆栈顶部发生的任何事情。实际上,这可能是保存的堆栈基指针。

printf("%d");

1
另一种选择是像main()一样传递一个数组,例如: int myfunc(type* argarray, int argcount);

0

C 可以让函数接收任意数量的参数。

你已经知道一个: printf()

printf("Hello World\n");
printf("%s\n", "Hello World");
printf("%d + %d is %d\n", 2, 2, 2+2);

没有接受任意数量参数的max函数,但编写自己的函数是一个很好的练习。

使用<stdarg.h>和该头文件中定义的va_listva_startva_argva_end标识符。

http://www.kernel.org/doc/man-pages/online/pages/man3/stdarg.3.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接