不,这称为重载,它不是 C 的功能。你最好创建 distinct 函数来处理这个问题。
你可以用各种 C 魔法来完成(你几乎可以用足够的 C 魔法来做任何事情),但是生成的代码可能太丑了,以至于无法维护:-)
例如,C11 引入了泛型选择,带有 _Generic 主表达式,这允许您根据输入参数类型调用不同的函数。实际上,它的作用远不止于此,但根据您的问题,这是您感兴趣的方面。
例如,假设您这样定义了两个函数:
int diffi (int a, int b) { return a - b; }
double diffd (double a, double b) { return a - b; }
通常,您必须根据您的输入类型来决定调用哪个。 C11 通用选择功能允许您这样做:
#define diff(a,b) \
_Generic((a), \
double: diffd, \
int: diffi, \
default: diffX \
)(a,b)
这基本上是在源代码中找到宏diff(x,y):
- 确定表达式
(a) 的类型,而不对其求值;
- 将与该类型匹配的令牌注入源流(如果未找到匹配则默认);
- 在源流末尾注入
(a,b) 文本。
所以,如果您的源文件包含以下行:
x = diff (1, 2);
y = diff (1.0, 2);
这将被翻译成:
x = diffi (1 , 2);
y = diffd (1.0, 2);
为您提供有效的超载。
现在这是一个比较简单的案例,因为它仅依赖于第一个参数类型 - 如果你尝试这样做,你会看到一个漏洞:
z = diff (1, 2.0);
因为 first 参数的类型是 int,所以你会得到:
z = diffi (1, 2.0);
这不是你真正想要做的。这就是复杂性所在,因为您必须涵盖 四种 可能性:{int/int, int/double, double/int, double/double} 并且根据参数的数量和每个参数的可能类型,它会变得更多复杂.
但是,您的完整案例可以通过明智地使用默认值和嵌套的通用选择来完成,例如:
#define diff(a,b) \
_Generic((a), \
double: diffd, \
default: _Generic((b), \
double: diffd, \
default: diffi \
) \
)(a,b)
这可以读作:
- 如果
a的类型为double,则使用diffd;
- 否则,如果
b的类型为double,则使用diffd;
- 否则,请使用
diffi。
- 别忘了也注入参数。
以下完整程序(使用clang 3.0 编译)展示了此功能的实际应用:
#include <stdio.h>
int diffi (int a, int b) {
printf ("diffi %d %d", a, b);
return a - b;
}
double diffd (double a, double b) {
printf ("diffd %f %f", a, b);
return a - b;
}
#define diff(a,b) \
_Generic((a), \
double: diffd, \
default: _Generic((b), \
double: diffd, \
default: diffi \
) \
)(a,b)
int main (void) {
int i; double d;
i = diff (1 , 2 ); printf (" --> %d\n", i);
d = diff (1.0, 2 ); printf (" --> %f\n", d);
d = diff (1 , 2.0); printf (" --> %f\n", d);
d = diff (1.0, 2.0); printf (" --> %f\n", d);
return 0;
}
该程序的输出是:
diffi 1 2 --> -1
diffd 1.000000 2.000000 --> -1.000000
diffd 1.000000 2.000000 --> -1.000000
diffd 1.000000 2.000000 --> -1.000000
表明针对四种可能性调用了正确的函数。
事实上,正如rici 在评论中指出的那样,您可以依赖 C 的提升规则,其中添加 double 和 int(以任何顺序)会给您一个 double 而添加两个int 变量会给你一个int:
#define diff(a,b) _Generic((a+b), double:diffd, default:diffi)(a,b)