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)

 
<think>嗯,用户的问题是关于函数重载函数重载的区别,以及C语言是否支持函数重载。首先,我需要确认这两个术语的具体含义,因为有时候不同的资料可能会有不同的叫法。 首先,函数重载(Function Overloading)应该是指在同一个作用域内,函数名相同但参数列表不同(类型、数量或顺序)。这允许程序员用同一个名字实现不同功能,根据参数自动选择对应的函数。比如C++中的例子,`add(int a, int b)`和`add(double a, double b)`就是重载函数。 接下来是“函数重载”这个术语。用户可能是指函数名的重复定义,或者是名称修饰(Name Mangling)的问题。不过通常来说,“函数重载”并不是一个标准术语,可能用户有误解,或者想了解其他相关概念。比如,可能是指函数名相同但通过不同方式处理,或者链接时的名称处理。但根据参考资料,C语言在编译时函数名不会进行修饰,所以无法区分同名函数的不同参数版本,导致不支持重载。 然后,关于C语言是否支持函数重载。根据引用[1]、[2]、[3]、[4],C语言确实不支持函数重载,因为它的编译器不会对函数名进行修饰,直接使用原函数名,导致链接时无法区分不同参数的函数。而C++通过名称修饰(比如参数类型编码到函数名中)来支持重载。 现在需要区分“函数重载”和“函数重载”的区别。可能用户将两者混淆了,或者“函数重载”是指其他机制。根据现有资料,没有提到函数重载,所以需要推测可能用户指的是函数名的重复定义,即同名函数,这在C语言中会导致冲突,而C++通过名称修饰避免这个问题。因此,可能函数重载并不存在,用户可能误用了术语,应该解释清楚。 接下来要组织答案,先明确两者的区别,然后解释C语言不支持函数重载的原因,并引用提供的资料来支持结论。需要确保回答结构清晰,分点说明,并使用正确的中文表达。同时要生成相关问题,可能需要围绕函数重载实现机制、C与C++的区别、名称修饰等方向提问。</think>### 函数重载函数重载的区别及C语言的支持性分析 #### 1. 函数重载 vs 函数重载 - **函数重载(Function Overloading)** 指在同一作用域内定义多个同名函数,但这些函数的参数列表不同(类型、数量或顺序)。例如: ```cpp int add(int a, int b); double add(double a, double b); ``` 编译器会根据调用时传入的参数类型自动选择匹配的函数版本[^1][^4]。 - **函数重载(非常规术语)** 该术语并不属于编程语言的标准化定义,可能是对以下两种概念的混淆: 1. **函数名重复定义**:在C语言中,若定义多个同名函数(即使参数不同),会引发编译错误,因为C编译器不会对函数名进行修饰[^2][^3]。 2. **函数名修饰(Name Mangling)**:在C++中,编译器通过将参数信息编码到函数名中(如`_add_int_int`),生成唯一的符号名称以支持重载。 #### 2. C语言是否支持函数重载? **不支持**,原因如下: 1. **无函数名修饰机制** C语言编译器直接使用原始函数名作为符号名称。例如函数`void foo(int a, int b)`会被存储为`foo`,而非包含参数信息的名称。若定义同名函数(即使参数不同),链接器无法区分它们,导致冲突[^3]。 2. **静态类型检查限制** C语言在编译时仅依赖函数名匹配调用,无法根据参数类型或数量动态选择函数版本。例如以下代码会报错: ```c void print(int x) {} void print(double x) {} // 编译错误:重复定义 ``` #### 3. 对比C++的实现 C++通过**函数名修饰**支持重载。例如: - `void foo(int, int)` → 符号名为`_foo_int_int` - `void foo(int, float)` → 符号名为`_foo_int_float` 编译器通过修饰后的名称区分不同参数列表的函数[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值