Question

Considérons le programme C suivant:

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

typedef void (callptr)();

static void fixed(void *something, double val)
{
    printf("%f\n", val);
}

static void dynamic(void *something, ...)
{
    va_list args;
    va_start(args, something);
    double arg = va_arg(args, double);
    printf("%f\n", arg);
}

int main()
{
    double x = 1337.1337;
    callptr *dynamic_func = (callptr *) &dynamic;
    dynamic_func(NULL, x);
    callptr *fixed_func = (callptr *) &fixed;
    fixed_func(NULL, x);

    printf("%f\n", x);
}

En fait, l'idée est de stocker une fonction avec des arguments variables dans un pointeur de fonction « générique ». A titre de comparaison, je l'ai également inclus une autre fonction avec liste d'arguments fixe. Maintenant, voyez ce qui se passe lors de l'exécution sur ce Linux x86, amd64 Linux, Win32 et Win64:

$ gcc -m32 -o test test.c
$ file test
test: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
$ ./test
1337.133700
1337.133700
1337.133700

$ gcc -o test test.c
$ file test
test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
$ ./test
1337.133700
1337.133700
1337.133700

C:\>gcc -o test.exe test.c
C:\>file test.exe
test.exe: PE32 executable for MS Windows (console) Intel 80386 32-bit
C:\>test.exe
1337.133700
1337.133700
1337.133700

C:\>x86_64-w64-mingw32-gcc -o test.exe test.c
C:\>file test.exe
test.exe: PE32+ executable for MS Windows (console) Mono/.Net assembly
C:\>test.exe
0.000000
1337.133700
1337.133700

Pourquoi la fonction dynamique obtenir une valeur nulle à partir de la liste d'arguments variable sur Win64, mais pas sur l'une des autres configurations? Est-ce quelque chose comme ça, même légal? Je suppose que c'est parce que le compilateur ne se plaignait pas.

Était-ce utile?

La solution

Votre code n'est pas valide. L'appel d'une fonction variadique nécessite un prototype indiquant qu'il est variadique, et le type de pointeur de fonction que vous utilisez ne fournit pas. Pour que l'appel à ne pas invoquer un comportement non défini, vous devez lancer le pointeur de dynamic_func comme celui-ci pour faire l'appel:

((void (*)(void *, ...))dynamic_func)(NULL, x);

Autres conseils

Vous devriez travailler avec des définitions de fonctions cohérentes, même si cela signifie utiliser VarArgs même si pas nécessaire. Le mieux est d'être aussi bavard au besoin.

...

typedef void myfunc_t(void *, ...);

...

myfunc_t dynamic;
void dynamic(void * something, ...)
{

...

}

...

int main()
{
    double x = 1337.1337;
    myfunc_t *callnow;
    callnow = &dynamic;
    callnow(NULL, x);

    printf("%f\n", x);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top