11

C语言如何像C++那样定义带“默认参数”的函数?

 3 years ago
source link: https://blog.popkx.com/c%E8%AF%AD%E8%A8%80%E5%A6%82%E4%BD%95%E5%83%8Fc%E9%82%A3%E6%A0%B7%E5%AE%9A%E4%B9%89%E5%B8%A6%E9%BB%98%E8%AE%A4%E5%8F%82%E6%95%B0%E7%9A%84%E5%87%BD%E6%95%B0/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

C语言如何像C++那样定义带“默认参数”的函数?

发表于 2019-09-03 20:09:45   |   已被 访问: 716 次   |   分类于:   C语言   |   暂无评论

使用C++开发过程序时,定义函数可以指定默认参数,例如 void fun(int x, int y=3); 在调用 fun() 时第二个参数可以不传递,此时 fun() 函数默认第二个参数等于 3,例如 f(1) 就相当于 f(1,3)。这是一个很好用的特性,那么在C语言程序开发中,是否也可以定义带“默认参数”的函数呢?

有“默认参数”的C语言函数

首先应该清楚,目前C语言还没有原生支持带默认参数的函数,也就是说下面这样的C语言代码是非法的:

void fun(int x, int y =3)
{
    return x+y;
}
fun(1);     // 不等价于 fun(1, 3)

但是,C语言作为一门极其灵活的编程语言,又的确可以借助其他基本语法实现这样的需求。不过要在C语言中定义带“默认参数”的函数可能略微有些繁琐,当然了,方法可能不止一种,本文不打算从枯燥的理论层面讨论这些方法,而是给出一个实例,希望能够起到抛砖引玉的作用。

假设我们希望在某段C语言程序中定义一个带默认参数的函数,它可以接收两个参数,并将之打印出来:

double f(int i, double x)
{
    printf("i=%d, x=%0.2f\n", i, x);
    return x;
}

现在期望调用 f 时,如果不显式指定参数,f 的两个默认参数为 (i=8, x=3.14),例如:

f(); // 输出 i=3, x=3.14
f(1); // 输出 i=1, x=3.14
f(2, 6.28); // 输出 i=2,x=6.28

C语言自然没有支持这种需求的原生语法,但是为了实现这样的目的,可以定义下面这个结构体,请看相关C语言代码:

typedef struct {
    int i;
    double x;
} f_args;

接着,定义 f_base() 函数,它的C语言代码实现和 f() 是一样的,目的是让 f_base() 函数具有期望的 f() 函数功能。然后再定义一个函数将 f_base() 封装,相关C语言代码如下,请看:

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

2739eb527f185ffb63a50e167868aa7d.png
显然,从上述C语言代码来看,var_f() 函数实现了默认参数的功能。现在再定义一个带可变参数的宏,这样一来,调用者就不必知道结构体 f_args 的结构了:

#define f(...) var_f((f_args){__VA_ARGS__})

现在我们就在C语言中实现了带“默认参数”的方法,全部C语言代码如下,请看:

c86513082a937c3caf9feeecfb9b64f2.png

上述C语言代码在 main() 函数中调用 f() 函数,并分别传递了不同的参数,编译并执行之,得到如下结果:
# gcc t.c
# ./a.out 
i=3, x=8.00
i=1, x=2.30
i=2, x=3.14
i=8, x=9.20

可见,C语言是一门极其简洁灵活的编程语言,其他编程语言中一些好用的特性,可能C语言没有原生语法支持,但是我们却可以组合其他基本语法,自己实现这些好用的特性。

不过应该注意,有件事是行不通的——f(0),因为上述实现我们无法在 var_f() 中区分 “0”究竟是调用者传递的,还是默认值,不过我相信聪明的读者应该能够想到解决这样的问题的方法。

阅读更多:   C语言


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK