Por que esse método para sobrecarga de função em C funciona?

Eu olhei algumas maneiras de fazê-lo em C, mas só encontrei o C99.

Mas me deparei com a solução abaixo, tirada deBloquear menos.

O problema é que eu não entendo muito bem como funciona e gostaria de conhecer os fundamentos do que está acontecendo lá para poder entendê-lo mais claramente.

Busquei a Web por um tempo e encontreiesta sobre__VA_ARGS__, mas isso por si só não foi suficiente, infelizmente.

Eu realmente aprecio uma explicação ou alguma orientação sobre esse assunto, qualquer tipo de referência ajudaria.

Eu compilei esse código comGCC-5.4.1 com-ansi bandeira.

#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>

#define COUNT_PARMS2(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _, ...) _
#define COUNT_PARMS(...)\
    COUNT_PARMS2(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

void count_overload1(int p1)
{
    printf("One param: %d\n", p1);
}

void count_overload2(double *p1, const char *p2)
{
    printf("Two params: %p (%f) %s\n", p1, *p1, p2);
}

void count_overload3(int p1, int p2, int p3)
{
    printf("Three params: %c %d %d\n", p1, p2, p3);
}

void count_overload_aux(int count, ...)
{
    va_list v;
    va_start(v, count);

    switch(count)
    {
        case 1:
        {
            int p1 = va_arg(v, int);
            count_overload1(p1);
            break;
        }

        case 2:
        {
            double *p1 = va_arg(v, double *);
            const char *p2 = va_arg(v, const char *);
            count_overload2(p1, p2);
            break;
        }

        case 3:
        {
            int p1 = va_arg(v, int);
            int p2 = va_arg(v, int);
            int p3 = va_arg(v, int);
            count_overload3(p1, p2, p3);
            break;
        }

        default:
        {
            va_end(v);

            printf("Invalid arguments to function 'count_overload()'");
            exit(1);
        }
    }

    va_end(v);
}
#define count_overload(...)\
    count_overload_aux(COUNT_PARMS(__VA_ARGS__), __VA_ARGS__)


int main(int argc, char const *argv[])
{
    double d = 3.14;
    count_overload(1);
    count_overload(&d, "test");
    count_overload('a',2,3);
    return 0;
}

A saída é:

One param: 1
Two params: 0x7ffc0fbcdd30 (3.140000) test
Three params: a 2 3

questionAnswers(2)

yourAnswerToTheQuestion