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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2988038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:37:00  来源:igfitidea点击:

Default values on arguments in C functions and function overloading in C

cfunctiondefaultoverloading

提问by inquam

Converting a C++ lib to ANSI C and it seems like though ANSI C doesn't support default values for function variables or am I mistaken? What I want is something like

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

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

Also, is function overloading possible in ANSI C?

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

Would need

需要

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

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

Could of course just name them differently but being used to C++ I kinda used to function overloading.

当然可以只是对它们进行不同的命名,但习惯于 C++ 我有点习惯于函数重载。

回答by

No, Standard C does not support either. Why do you feel you need to convert your C++ code to C? That could get quite tricky - I'd have thought writing wrappers would be the way to go, if your C++ must be callable from C.

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

回答by user941239

Nevertheless I found a "trick" to do so if you use GCC.

不过,如果您使用 GCC,我发现了一个“技巧”。

GCC has a handy ## extension on variadic macro that allows you to simulate a default argument.

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

The trick has limitations: it works only for 1 default value, and the argument must be the last of you function parameters.

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

Here is a working example.

这是一个工作示例。

#include <stdio.h>


#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 ) );

}

In this case, I define SUM as a call to sum with the default second argument being 5.

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

If you call with 2 arguments (first call in main), it would be prepocessed as: sum( 3, (5, 7) );

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

This means:

这意味着:

  • 1st argument is 3
  • second argument is the result of the sequence (5, 7)... which is obviously 7!
  • 第一个参数是 3
  • 第二个参数是序列 (5, 7) 的结果……显然是 7!

As gcc is clever, this has no effect on runtime as the first member of the sequence is a constant and it is not needed, it will simply be discarded at compile time.

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

If you call with only one argument, the gcc extension will remove the VA_ARGS ANDthe leading coma. So it is preprocessed as:

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

sum( 3, (5 ) );

总和( 3, (5 ) );

Thus the program gives the expected output:

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

10
8

So, this does perfectly simulate (with the usual macro limitations) a function with 2 arguments, the last one being optional with a default value applied if not provided.

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

Edit

编辑

-a) It does also work with CLANG (and possibly other compilers)

-a) 它也适用于 CLANG(可能还有其他编译器)

-b) A version that does NOT complain about unused arguments:

-b) 不抱怨未使用参数的版本:

#define DEF_OR_ARG(z,a,arg,...) arg
#define SUM(a,...) sum( a, DEF_OR_ARG(,##__VA_ARGS__,__VA_ARGS__,5))

回答by user7828

Try this.

尝试这个。

#include <stdio.h>
#include <stdarg.h>

/* 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;
}

回答by John Ritchie

There is a way to support as many default parameters you need, just use a structure.

有一种方法可以支持您需要的尽可能多的默认参数,只需使用结构即可。

// 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;
  }
}

回答by Amnon

As far as I know ANSI C doesn't directly support function overloading or default arguments. The standard substitute for overloading is adding suffixes to the function name indicating the argument types. For example, in OpenGL, a "3fv" suffix to a function name means the function takes a vector of three floats.

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

Default arguments can be viewed as a special case of function overloading.

默认参数可以看作是函数重载的一种特殊情况。

回答by ShinTakezou

You can't so easily since C does not support them. The simpler way to get "fake overloading" is using suffixes as already said... default values could be simulated using variable arguments function, specifying the number of args passed in, and programmatically giving default to missing one, e.g.:

你不能那么容易,因为 C 不支持它们。获得“假重载”的更简单方法是使用已经说过的后缀……可以使用可变参数函数模拟默认值,指定传入的参数数量,并以编程方式将默认值设置为缺少一个,例如:

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

Also overloading can be simulated using var args with extra informations to be added and passed and extracode... basically reproducing a minimalist object oriented runtime ... Another solution (or indeed the same but with different approach) could be using tags: each argument is a pair argument type + argument (an union on the whole set of possible argument type), there's a special terminator tag (no need to specify how many args you're passing), and of course you always need "collaboration" from the function you're calling, i.e. it must contain extra code to parse the tags and choose the actual function to be done (it behaves like a sort of dispatcher)

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

回答by Hans Insulander

Neither of default values or function overloading exists in ANSI C, so you'll have to solve it in a different way.

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

回答by INS

You'll have to declare each C++ overloaded function differently in C because C doesn't do name mangling. In your case "foo_property1" "foo_property2".

您必须在 C 中以不同方式声明每个 C++ 重载函数,因为 C 不执行name mangling。在你的情况下“foo_property1”“foo_property2”。

回答by baz

i think u can use a function with variable arguments here is my example

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

#include <stdarg.h>
#include <stdio.h>
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;
}

the output is

输出是

baz
foo
baz
bar

if u look for example man 2 open they say

如果你寻找例如 man 2 open 他们说

SYNOPSIS
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>

       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);

but mode is actually a ... argument

但 mode 实际上是一个 ... 参数