有没有一种方法可以在C语言中指定函数的默认参数?


当前回答

你不需要只在c上使用VARARGS,下面是一个例子。

int funcA_12(int a1, int a2) { ... }

#define funcA(a1) funcA_12(a1, 0)

这个答案与上面的两个函数方法非常相似,但在这种情况下,您使用的是定义参数的函数名宏。

其他回答

哇,这里的每个人都这么悲观。答案是肯定的。

这并不简单:到最后,我们将拥有核心函数、支持结构、包装器函数和宏 围绕包装器函数。在我的工作中,我有一组宏来自动化所有这些;一次 你了解流程,你也会很容易做到。

我已经在其他地方写过了,所以这里有一个详细的外部链接来补充这里的摘要:http://modelingwithdata.org/arch/00000022.htm

我们想转弯

double f(int i, double x)

变成一个接受默认值的函数(i=8, x=3.14)。定义一个伴生结构:

typedef struct {
    int i;
    double x;
} f_args;

将函数重命名为f_base,并定义一个设置默认值和调用的包装器函数 基础:

double var_f(f_args in){
    int i_out = in.i ? in.i : 8;
    double x_out = in.x ? in.x : 3.14;
    return f_base(i_out, x_out);
}

现在添加一个宏,使用C的可变宏。这样用户就不需要知道他们是 实际上填充一个f_args结构体,并认为他们在做通常的事情:

#define f(...) var_f((f_args){__VA_ARGS__});

好了,现在所有下面的都可以工作了:

f(3, 8);      //i=3, x=8
f(.i=1, 2.3); //i=1, x=2.3
f(2);         //i=2, x=3.14
f(.x=9.2);    //i=8, x=9.2

检查复合初始化器如何为确切的规则设置默认值的规则。

有一件事是行不通的:f(0),因为我们无法区分缺失的值和 零。根据我的经验,这是需要注意的事情,但可以作为照顾 这种需求出现了——有一半的情况下,你的违约实际上是零。

我费了这么大劲写出来是因为我认为命名参数和默认值 确实让用C编写代码变得更简单,更有趣。和 C语言太棒了,因为它如此简单,而且仍然有足够的内容使这一切成为可能。

不,那是c++语言的特性。

使用宏的另一个技巧:

#include <stdio.h>

#define func(...) FUNC(__VA_ARGS__, 15, 0)
#define FUNC(a, b, ...) func(a, b)

int (func)(int a, int b)
{
    return a + b;
}

int main(void)
{
    printf("%d\n", func(1));
    printf("%d\n", func(1, 2));
    return 0;
}

如果只传递一个参数,则b接收默认值(在本例中为15)

YES

通过宏

三个参数:

#define my_func2(...) my_func3(__VA_ARGS__, 0.5)
#define my_func1(...) my_func2(__VA_ARGS__, 10)
#define VAR_FUNC(_1, _2, _3, NAME, ...) NAME
#define my_func(...) VAR_FUNC(__VA_ARGS__, my_func3, my_func2, my_func1)(__VA_ARGS__)

void my_func3(char a, int b, float c) // b=10, c=0.5
{
    printf("a=%c; b=%d; c=%f\n", a, b, c);
}

如果你想要第4个参数,那么需要添加一个额外的my_func3。注意VAR_FUNC、my_func2和my_func中的变化

4个参数:

#define my_func3(...) my_func4(__VA_ARGS__, "default") // <== New function added
#define my_func2(...) my_func3(__VA_ARGS__, (float)1/2)
#define my_func1(...) my_func2(__VA_ARGS__, 10)
#define VAR_FUNC(_1, _2, _3, _4, NAME, ...) NAME
#define my_func(...) VAR_FUNC(__VA_ARGS__, my_func4, my_func3, my_func2, my_func1)(__VA_ARGS__)

void my_func4(char a, int b, float c, const char* d) // b=10, c=0.5, d="default"
{
    printf("a=%c; b=%d; c=%f; d=%s\n", a, b, c, d);
}

唯一的例外是,浮动变量不能被赋予默认值(除非它是3个参数情况下的最后一个参数),因为它们需要句号('.'),这在宏参数中是不被接受的。但可以找出一个工作周围看到my_func2宏(4个参数的情况下)

程序

int main(void)
{
    my_func('a');
    my_func('b', 20);
    my_func('c', 200, 10.5);
    my_func('d', 2000, 100.5, "hello");

    return 0;
}

输出:

a=a; b=10; c=0.500000; d=default                                                                                                                                                  
a=b; b=20; c=0.500000; d=default                                                                                                                                                  
a=c; b=200; c=10.500000; d=default                                                                                                                                                
a=d; b=2000; c=100.500000; d=hello  

一般不会,但在gcc中,你可以使用宏将funcA()的最后一个参数设置为可选的。

在funcB()中,我使用了一个特殊的值(-1)来表示我需要'b'参数的默认值。

#include <stdio.h> 

int funcA( int a, int b, ... ){ return a+b; }
#define funcA( a, ... ) funcA( a, ##__VA_ARGS__, 8 ) 


int funcB( int a, int b ){
  if( b == -1 ) b = 8;
  return a+b;
}

int main(void){
  printf("funcA(1,2): %i\n", funcA(1,2) );
  printf("funcA(1):   %i\n", funcA(1)   );

  printf("funcB(1, 2): %i\n", funcB(1, 2) );
  printf("funcB(1,-1): %i\n", funcB(1,-1) );
}