Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
397 views
in Technique[技术] by (71.8m points)

mingw - How to use varargs in conjunction with function pointers in C on Win64?

Consider the following C program:

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

typedef void callptr();

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

static void dynamic(void *something, ...)
{
    va_list args;
    va_start(args, something);
    double arg = va_arg(args, double);
    printf("%f
", 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
", x);
}

Basically, the idea is to store a function with variable arguments in a "generic" function pointer. As a comparison, I've also included another function with fixed argument list. Now see what happens when running this on x86 Linux, amd64 Linux, Win32 and 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

Why does the dynamic function get a zero value from the variable argument list on Win64, but not on any of the other configurations? Is something like this even legal? I assumed it is because the compiler didn't complain.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your code is not valid. Calling a variadic function requires a prototype indicating that it's variadic, and the function pointer type you're using does not provide this. In order for the call not to invoke undefined behavior, you would have to cast the dynamic_func pointer like this to make the call:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...