如何在Win64上的C语言中将varargs与函数指针结合使用?

问题描述 投票:6回答:2

考虑以下C程序:

#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);
}

[基本上,想法是将带有可变参数的函数存储在“通用”函数指针中。作为比较,我还包括了另一个带有固定参数列表的函数。现在看看在x86 Linux,amd64 Linux,Win32和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

为什么动态函数从Win64上的变量参数列表中获取零值,而在其他任何配置上却没有?这样的事情合法吗?我以为是因为编译器没有抱怨。

c mingw function-pointers variadic-functions mingw-w64
2个回答
6
投票

您的代码无效。调用可变参数函数需要一个表明其可变参数的原型,而您使用的函数指针类型不提供此功能。为了使调用不会调用未定义的行为,您必须像这样强制转换dynamic_func指针才能进行调用:

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

2
投票

即使您不需要使用varargs,也应使用一致的函数定义。最好是根据需要进行详细说明。

...

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);
}
© www.soinside.com 2019 - 2024. All rights reserved.