C语言中参数的默认值和C中的函数重载

将C ++库转换为ANSI C,似乎ANSI C不支持函数变量的默认值,或者我错了? 我想要的是类似的东西

int funcName(int foo, bar* = NULL); 

另外,ANSI C中的函数重载是否可行?

需要

 const char* foo_property(foo_t* /* this */, int /* property_number*/); const char* foo_property(foo_t* /* this */, const char* /* key */, int /* iter */); 

当然可以用不同的方式命名它们但是习惯于C ++我曾经用于函数重载。

不,标准C也不支持。 为什么您认为需要将C ++代码转换为C? 这可能会变得非常棘手 – 如果您的C ++必须可以从C调用,我认为编写包装器是可行的方法。

然而,如果你使用GCC,我发现了一个“技巧”。

GCC在variadic宏上有一个方便的##扩展,允许你模拟一个默认参数。

技巧有局限性:它仅适用于1个默认值,参数必须是最后一个函数参数。

这是一个有效的例子。

 #include  #define SUM(a,...) sum( a, (5, ##__VA_ARGS__) ) int sum (a, b) int a; int b; { return a + b; } main() { printf("%d\n", SUM( 3, 7 ) ); printf("%d\n", SUM( 3 ) ); } 

在这种情况下,我将SUM定义为对sum的调用,默认的第二个参数为5。

如果你用2个参数调用(在main中首次调用),它将被预处理为:sum(3,(5,7));

这意味着:

  • 第一个参数是3
  • 第二个参数是序列(5,7)的结果……显然是7!

由于gcc很聪明,这对运行时没有影响,因为序列的第一个成员是常量而不需要它,它将在编译时被丢弃。

如果只使用一个参数调用,gcc扩展名将删除VA_ARGS 前导昏迷。 所以它被预处理为:

sum(3,(5));

因此程序给出了预期的输出:

 10 8 

因此,这完全模拟了(通常的宏限制)具有2个参数的函数,最后一个是可选的,如果未提供则应用默认值。

据我所知,ANSI C不直接支持函数重载或默认参数。 重载的标准替代是在函数名称中添加后缀,指示参数类型。 例如,在OpenGL中,函数名称的“3fv”后缀表示该函数采用三个浮点数的向量。

默认参数可以视为函数重载的特例。

有一种方法可以支持所需的默认参数,只需使用结构即可。

 // Populate structure with var list and set any default values struct FooVars { int int_Var1 = 1; // One is the default value char char_Command[2] = {"+"}; float float_Var2 = 10.5; }; struct FooVars MainStruct; //... // Switch out any values needed, leave the rest alone MainStruct.float_Var2 = 22.8; Myfunc(MainStruct); // Call the function which at this point will add 1 to 22.8. //... void Myfunc( struct FooVars *MyFoo ) { switch(MyFoo.char_Command) { case '+': printf("Result is %i %c %f.1 = %f\n" MyFoo.int_Var1, MyFoo.char_Command, MyFoo.float_Var2, (MyFoo.float_Var2 + MyFoo.int_Var1); break; case '*': // Insert multiply here, you get the point... break; case '//': // Insert divide here... break; } } 

试试这个。

 #include  #include  /* print all non-negative args one at a time; all args are assumed to be of int type */ void printargs(int arg1, ...) { va_list ap; int i; va_start(ap, arg1); for (i = arg1; i >= 0; i = va_arg(ap, int)) printf("%d ", i); va_end(ap); putchar('\n'); } int main(void) { printargs(5, 2, 14, 84, 97, 15, 24, 48, -1); printargs(84, 51, -1); printargs(-1); printargs(1, -1); return 0; } 

ANSI C中不存在默认值或函数重载,因此您必须以不同的方式解决它。

你不能这么容易,因为C不支持它们。 获得“伪重载”的简单方法是使用后缀,如前所述…默认值可以使用变量参数函数进行模拟,指定传入的args数量,并以编程方式给出缺省值,例如:

  aType aFunction(int nargs, ...) { // "initialization" code and vars switch(nargs) { case 0: // all to default values... eg aVar1 = 5; // ... break; case 1: aVar1 = va_arg(arglist, int); //... // initialize aVar2, 3, ... to defaults... break; // ... } } 

还可以使用var args模拟重载,添加和传递额外信息和extracode …基本上再现一个极简主义的面向对象的运行时…另一种解决方案(或者实际上相同但使用不同的方法)可以使用标签:每个参数是一对参数类型+参数(整个可能的参数类型集合上的一个联合),有一个特殊的终结符标签(不需要指定你传递了多少个args),当然你总是需要“协作”来自你正在调用的函数,即它必须包含额外的代码来解析标记并选择要完成的实际函数(它的行为类似于一种调度程序)

你必须在C中以不同的方式声明每个C ++重载函数,因为C不会进行名称修改 。 在你的情况下“foo_property1”“foo_property2”。

我想你可以使用带有可变参数的函数,这是我的例子

 #include  #include  void baz( int flag, ... ) { va_list ap; char *bar = "baz"; /* default value */ va_start( ap, flag ); if ( flag == 1 ) bar = va_arg( ap, char * ); va_end( ap ); printf( "%s\n", bar ); } int main( void ) { baz( 0 ); baz( 1, "foo"); baz( 2 ); baz( 1, "bar"); return 0; } 

输出是

 baz foo baz bar 

如果你看例如男人2打开他们说

 SYNOPSIS #include  #include  #include  int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); int creat(const char *pathname, mode_t mode); int openat(int dirfd, const char *pathname, int flags); int openat(int dirfd, const char *pathname, int flags, mode_t mode); 

但模式实际上是……论证