在Java中,当方法具有相同名称时,我们可以进行重载。我在谷歌上搜索,它说 C 不支持重载,所以我想知道是否有一种方法可以做类似于 C 中的重载的事情。
例如:
int max(int num1, int num2);
double max(double num1, num2);
int main(){
printf(...);
printf(...);
}
int max(int num1, int num2){
...
}
double max(double num1, double num2){
...
}
Run Code Online (Sandbox Code Playgroud)
您找到的参考是正确的:C 本身不支持重载。
它所拥有的(假设我们谈论的是实际的 C 而不是历史版本)是一个通用选择器,它允许您编写自己的宏来进行动态调度。
C99 引入了tgmath.h标头,它允许重载某些数学函数,以便与不同宽度的浮点参数一起使用,在某些情况下还可以使用复杂的参数。然而,C99 中没有引入允许将该功能推广到其他功能的设施。C11 中引入的通用选择器就是这样的工具。
选择器的形式为_Generic(select-expression, type-associations),其中type-associations由逗号分隔的形式对列表组成type : expression。选择器将被替换为与 的类型对应的表达式select-expression。其中 s 之一type可以是关键字default;其他的必须是唯一的完整类型(即列表中的两种类型不能兼容)[注1]。需要注意的是,关联列表中的所有表达式都必须无错误地编译,而不仅仅是最终选择的表达式。通常,表达式是函数指针,而不是函数调用。
一个例子可能会让这一点更清楚。假设我们有两个函数(它们具有不同的名称,因此这不是名称重载):
int max_int(int a, int b) { return a > b ? a : b; }
double max_dbl(double a, double b) { return a > b ? a : b; }
Run Code Online (Sandbox Code Playgroud)
现在,我们可以定义宏 MAX:
#define MAX(a, b) _Generic((a)+(b), \
int : max_int, \
double : max_dbl)(a, b)
Run Code Online (Sandbox Code Playgroud)
在这里,我使用a+bas 选择器表达式而不是a,因为 的类型a+b是通常算术转换产生的类型。如果我刚刚使用a, thenMAX(3, 5.7)会产生意外的结果,因为通用选择器将被选择max_int并被5.7默默地截断为 5。使用 时a+b,选择器的类型将为double,导致调用max_dbl,其中两个值都是转换为双倍。
我可以不用(a)+(b)在宏中使用,因为_Generic它不会计算选择器表达式(如sizeof)。因此,不存在对具有副作用的参数进行双重评估的危险。