Function overloading in C
Tags: c, programming, tutorial
Published: 2023-07-08 15:07:46

Function overloading is regarded as powerful feature in programming languages. It allows developers to define multiple functions that take different arguments while having the same name.

This can be a convenient method of writing code that is more readable, maintainable, and reusable. 

In C, function overloading is not a built-in feature, but it can be achieved through a technique called "name mangling" or "function name decoration" (more on that in an upcoming post). 

In this post, we will explore some methods that can help us achieve function overloading in C.



### Using `_Generic` keyword/macro

While function overloading is not supported in C, you can achieve similar functionality by using the `_Generic` keyword, which is available in C11 and later

```c
#include <stdio.h>

#define double_num(x) _Generic((x), \
    int: double_int, \
    float: double_float, \
    long: double_long \
)(x)

int double_int(int num) {
    return num * 2;
}

float double_float(float num) {
    return num * 2.0;
}

long double_long(long num) {
    return num * 2;
}

int main() {
    int v1 = 2;
    float v2 = 3.0f;
    long v3 = 4;

    int x = double_num(v1);
    printf("%d doubled again is %d\n", v1, x);
    
    float y = double_num(v2);
    printf("%f doubled again is %f\n", v2, y);
    
    long z = double_num(v3);
    printf("%ld doubled again is %ld\n", v3, z);   
    
    return 0;

}
```

### Using clang attribute `overloadable`:

The Clang compiler, compiler that supports multiple programming languages including OpenMP, OpenCL and other framework, has a feature called **attributes** which are used to declare additional information about the behavior of functions, variables, types, and other language constructs.

The `overloadable` attribute can be used to achieve function overloading in C.

```c
#include <stdio.h>

__attribute__((overloadable)) int double_num(int num) {
    return num * 2;
}

__attribute__((overloadable)) float double_num(float num) {
    return num * 2.0;
}

__attribute__((overloadable)) long double_num(long num) {
    return num * 2;
}


int main() {
    int v1 = 2;
    float v2 = 3.0f;
    long v3 = 4;

    int x = double_num(v1);
    printf("%d doubled again is %d\n", v1, x);
    
    float y = double_num(v2);
    printf("%f doubled again is %f\n", v2, y);
    
    long z = double_num(v3);
    printf("%ld doubled again is %ld\n", v3, z);
    
    return 0;

}
```



The `overloadable` attribute is a Clang-specific extension, so it is not portable to other compilers. This means that if you use this attribute, your code may not compile with other compilers such as GCC or MSVC. There are also some caveats that come with using attributes. If you're interested in knowing more about how they work, be sure to check the link in the references section.



### Using `varargs`

In C, `varargs` refers to a feature that allows functions to accept a variable number of arguments. This is achieved through the use of the `stdarg.h` header file, which defines a set of macros for accessing the arguments passed to a function.

A function that uses `varargs` must include an ellipsis (`...`) as the last parameter in its parameter list. This indicates that the function can accept additional arguments after the named parameters. The `va_list`, `va_start`, `va_arg`, and `va_end` macros are then used within the function to access these additional arguments.

```c
#include <stdio.h>
#include <stdarg.h>
#include <string.h>


int double_num(const char* format, ...) {
    va_list args;
    va_start(args, format);
    if (strcmp(format, "%d") == 0) {
        int num = va_arg(args, int);
        va_end(args);
        return num * 2;
    } else if (strcmp(format, "%f") == 0) {
        float num = va_arg(args, double);
        va_end(args);
        return num * 2.0;
    } else if (strcmp(format, "%ld") == 0) {
        long num = va_arg(args, long);
        va_end(args);
        return num * 2;
    }
    va_end(args);
    return 0;
}

int main() {

    int v1 = 2;
    float v2 = 3.0f;
    long v3 = 4;
    
    int x = double_num("%d", v1);
    printf("%d doubled again is %d\n", v1, x);
    
    float y = double_num("%f", v2);
    printf("%.2f doubled again is %.2f\n", v2, y);
    
    long z = double_num("%ld", v3);
    printf("%ld doubled again is %ld\n", v3, z);
    
    return 0;

}
```



In a following post, we'll explore more on what this actually translates to in terms of the compile file that runs this code.

 `Note: All the previous code, apart from the clang one, were built with gcc. The clang one can be built using the same style as gcc. You just have to replace gcc with clang in your command`



## References

https://clang.llvm.org/docs/AttributeReference.html
https://www.udacity.com/blog/2021/09/cp-function-overloading-what-you-need-to-know.html
https://learn.microsoft.com/en-us/cpp/cpp/function-overloading?view=msvc-170
https://stackoverflow.com/questions/36504216/function-overloading-in-c-without-using-generic
https://stackoverflow.com/questions/64408323/how-to-overload-functions-in-c
[Attributes in Clang — Clang 17.0.0git documentation (llvm.org)](https://clang.llvm.org/docs/AttributeReference.html#overloadable)