有没有一种方法可以在C语言中指定函数的默认参数?
当前回答
https://github.com/cindRoberta/C/blob/master/structure/function/default_parameter.c
#include<stdio.h>
void f_impl(int a, float b) {
printf("%d %g\n", a, b);
}
#define f_impl(...) f_macro(__VA_ARGS__, 3.7)
#define f_macro(a, b, ...) f_impl(a, b)
int main(void) {
f_impl(1);
f_impl(1, 2, 3, 4);
return 0;
}
其他回答
不,那是c++语言的特性。
一般不会,但在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) );
}
还有一个选项使用结构体:
struct func_opts {
int arg1;
char * arg2;
int arg3;
};
void func(int arg, struct func_opts *opts)
{
int arg1 = 0, arg3 = 0;
char *arg2 = "Default";
if(opts)
{
if(opts->arg1)
arg1 = opts->arg1;
if(opts->arg2)
arg2 = opts->arg2;
if(opts->arg3)
arg3 = opts->arg3;
}
// do stuff
}
// call with defaults
func(3, NULL);
// also call with defaults
struct func_opts opts = {0};
func(3, &opts);
// set some arguments
opts.arg3 = 3;
opts.arg2 = "Yes";
func(3, &opts);
哇,这里的每个人都这么悲观。答案是肯定的。
这并不简单:到最后,我们将拥有核心函数、支持结构、包装器函数和宏 围绕包装器函数。在我的工作中,我有一组宏来自动化所有这些;一次 你了解流程,你也会很容易做到。
我已经在其他地方写过了,所以这里有一个详细的外部链接来补充这里的摘要: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语言太棒了,因为它如此简单,而且仍然有足够的内容使这一切成为可能。