有没有一种方法可以在C语言中指定函数的默认参数?
当前回答
哇,这里的每个人都这么悲观。答案是肯定的。
这并不简单:到最后,我们将拥有核心函数、支持结构、包装器函数和宏 围绕包装器函数。在我的工作中,我有一组宏来自动化所有这些;一次 你了解流程,你也会很容易做到。
我已经在其他地方写过了,所以这里有一个详细的外部链接来补充这里的摘要: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语言太棒了,因为它如此简单,而且仍然有足够的内容使这一切成为可能。
其他回答
No.
即使是最新的C99标准也不支持这一点。
一般不会,但在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) );
}
简单的回答:不。
稍微长一点的回答:有一个很老很老的解决方法,你传递一个字符串来解析可选参数:
int f(int arg1, double arg2, char* name, char *opt);
哪里的opt可能包括“name=value”对或其他东西,你会叫喜欢吗
n = f(2,3.0,"foo","plot=yes save=no");
显然,这只是偶尔有用。一般来说,当你想要一个单一的接口到一系列功能时。
你仍然可以在专业程序用c++编写的粒子物理代码中找到这种方法(例如ROOT)。它的主要优点是可以几乎无限期地扩展,同时保持向后兼容性。
还有一个选项使用结构体:
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);
OpenCV使用的是:
/* in the header file */
#ifdef __cplusplus
/* in case the compiler is a C++ compiler */
#define DEFAULT_VALUE(value) = value
#else
/* otherwise, C compiler, do nothing */
#define DEFAULT_VALUE(value)
#endif
void window_set_size(unsigned int width DEFAULT_VALUE(640),
unsigned int height DEFAULT_VALUE(400));
如果用户不知道他应该写什么,这个技巧会很有用: