質問

次の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の変数引数リストからゼロ値を取得するのに、他の構成のいずれでもないのはなぜですか?このようなものは合法ですか?コンパイラが文句を言わなかったからだと思いました。

役に立ちましたか?

解決

あなたのコードは無効です。バリアード関数を呼び出すには、それがバリアードであることを示すプロトタイプが必要であり、使用している関数ポインタータイプはこれを提供しません。コールが未定義の動作を呼び出さないためには、 dynamic_func このようなポインターは電話をかけます:

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

他のヒント

必要でなくても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);
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top