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);
但模式实际上是……论证