C语言实现的函数重载

重载简单来说就是一个函数名可以实现不同的功能,要么输入参数不同或者参数个数不同,要么返回类型不同。
    众所周知,c++允许重载函数(而C不允许)。这通常是通过“篡改”函数名来实现的,从而在符号定义中包含函数参数的类型。然后,重载函数的每个变体将获得入口点的不同符号名。因此,通过调用或跳转到正确的符号,我们可以执行函数的正确版本。
    通常,C编译器根本不需要对函数符号名进行任何修改(这是忽略下划线的技巧)。这意味着您不能简单地定义一个函数的两个版本。它们会得到相同的符号名,链接器会抱怨。
    然而,这并不是故事的全部。C和POSIX标准的各个部分都需要C函数的重载版本。其中最简单的是open()函数的定义。这个函数有两个参数,第一个参数描述要打开的文件的路径,第二个参数描述如何正确打开文件。还有一个可选的第三个参数,只有在可能创建文件时才需要它。第三个参数描述了新文件使用的权限设置。
 
1、根据 "参数个数" 实现重载
#include <stdio.h>
#include <stdarg.h>
void va_overload2(int p1, int p2)
{
    printf("va_overload2 %d %d\n", p1, p2);
}
 
void va_overload3(int p1, int p2, int p3)
{
    printf("va_overload3 %d %d %d\n", p1, p2, p3);
}
 
static void va_overload(int p1, int p2, ...)
{
    if (p2 == 7)
    {
        a_list v;
        va_start(v, p2);
                
        int p3 = va_arg(v, int);
        va_end(v);
        va_overload3(p1, p2, p3);
 
        return;
     }
 
     va_overload2(p1, p2);
}
 
2、根据 "宏和预处理" 实现重载
void cpp_overload1(int p1)
{
        printf("CPP One param: %d\n", p1);
}
 
void cpp_overload2(double *p1, const char *p2)
{
        printf("CPP Two params: %p (%f) %s\n", p1, *p1, p2);
}
 
void cpp_overload3(int p1, int p2, int p3)
{
        printf("CPP Three params: %c %d %d\n", p1, p2, p3);
}
 
#define CAT(A, B) CAT2(A, B)
#define CAT2(A, B) A ## B
 
#define cpp_overload(...)\
         CAT(cpp_overload, COUNT_PARMS(__VA_ARGS__))(__VA_ARGS__)
 
3、根据 "函数指针" 实现重载
typedef struct _int_param {
    int param1;
    int param2;
}INT_PARAM;
 
typedef struct _double_param_ {
    double param1;
    double param2;
}DOUBLE_PARAM;
 
typedef void* (*ADDFUNC)(void*);
 
 
void* int_add_func(void* wParam)
{
    INT_PARAM* lParam = (INT_PARAM*)wParam;
    int res = lParam->param1 + lParam->param2;
    return (void*)&res;
}
 
 
void* double_add_func(void* wParam)
{
    DOUBLE_PARAM* lParam = (DOUBLE_PARAM*)wParam;
    double res = lParam->param1 + lParam->param2;
    return (void*)&res;
}
 
 
void* add_func(ADDFUNC f, void* wParam)
{
    return f(wParam);
}
 
 
int test()
{
    INT_PARAM val1 = {10, 20};
 
    DOUBLE_PARAM val2 = {30.5, 40.5};
 
    void* res1 = add_func(int_add_func, &val1);
     int result1 = *((int*)res1);
 
    void* res2 = add_func(double_add_func, &val2);
     double result2 = *((double*)res2);
 
    return 0;
}
 
4、根据 "gcc内置函数" 实现重载
__builtin_types_compatible_p()       __builtin_choose_expr()
 

void gcc_type_overload_aux(int typeval, ...)
{
    switch(typeval)
    {
        case 1:
        {
            va_list v;
            va_start(v, typeval);
            struct s1 s = va_arg(v, struct s1);
            va_end(v);
            gcc_overload_s1(s);
            break;
        }

        case 2:
        {
            va_list v;
            va_start(v, typeval);
            struct s2 s = va_arg(v, struct s2);
            va_end(v);
            gcc_overload_s2(s);
            break;
        }

        default:
        {
            printf("Invalid type to 'gcc_type_overload()'\n");
            exit(1);
        }
    }
}

#define gcc_type_overload(A)\

    gcc_type_overload_aux(\
        __builtin_types_compatible_p(typeof(A), struct s1) * 1\
        + __builtin_types_compatible_p(typeof(A), struct s2) * 2\
        , A)

 
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值