비원형 함수의 선언은 가변인자를 가지는 함수와는 호환될 수 없다.

아래는 비원형 선언엔 대한 포인터를 통해 가변인자를 가지는 함수를 호출하려 할때  정의되지 않은 행동(undefined behavior)을 보여주는 예이다.



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




$ 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에서는 0을 출력한다.


함수 포인터(pointer to function)은 내부표현이나 정렬제한(alignment requirement)문제를 가지지 않기때문에 호환되지 않는 함수의 포인터를 가질 수 있지만, 호출을 할때는 호환되는 함수형을 가지고 있어야 한다. 만약 그렇지 않다면 정의되지 않은 행동(undefined behavior)이며, 이는 위와 같이 임플리멘테이션(implementation)에 따라 결과가 달라질 수 있다.


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

따라서 위와 같이 호환되는 함수형으로 호출하여야 한다.



( http://stackoverflow.com/questions/7308449/how-to-use-varargs-in-conjunction-with-function-pointers-in-c-on-win64 )

Posted by shany0_0
,