2012-11-18 7 views
5

가능한 중복 다음 통해 호출하는 경우
Casting a function pointer to another typeC에서 정의 된 함수 포인터를 통해 추가 매개 변수를 전달합니까?

이 기능은 여전히 ​​제대로 수행, 내가 실제로 다음 함수 포인터 정의를 적은 매개 변수를받는 함수와 함수 포인터를 초기화 가정 함수 포인터?

나는 GCC와 함께이 시도 예상대로 일했다,하지만 난 그 행동이 (내가 그것을 스택에 위력을 과시 수있는 몇 가지 enviroments에에 의심) 컴파일러/플랫폼에서 일관성이 궁금 :

#include <stdio.h> 

typedef void (*myfun)(int, int, int); 

void test_a(int x, int y, int z) { 
    printf("test_a %d %d %d\n", x, y, z); 
} 

void test_b(int x, int y) { 
    printf("test_b %d %d\n", x, y); 
} 

int main() { 
    myfun fp; 
    fp = test_a; 
    fp(1, 2, 3); 
    fp = (myfun) test_b; 
    fp(4, 5, 6); 
} 

답변

4

프로그램의 동작이 정의되지 않았습니다. 사실 컴파일러가 캐스트한다는 것은 컴파일러에게 "이것은 잘못된 것이지만 어쨌든 할 수 있습니다"라고 알려주기 때문입니다. 당신이 캐스트를 제거하면 해당 오류 메시지를 얻을 것이다 : (. gcc -Wall -Werror에서)

a.c:17:8: error: assignment from incompatible pointer type [-Werror] 

은보다 구체적으로, 동작은 호출 규칙에 따라 달라집니다. 인수가 스택에서 "역순"으로 전달 된 플랫폼에 있다면 프로그램은 매우 다른 결과를 나타냅니다.

+1

또한 피 호출자 정리를 사용하면 충돌이 발생할 수 있습니다. 나는 –

+0

을 본다. 'typedef void (* myfun)() '와 같이 매개 변수 목록없이 함수 포인터 유형을 정의하는 것은 어떻습니까? 컴파일러는이 경우 스택의 매개 변수 순서가 "옳다"라고 보장해야합니까? – Askaga

+0

@BillAskaga No : 원하는 것을 "보장"하려면 대상 함수와 함수 포인터가 모두 [cdecl calling convention]을 사용해야합니다 (http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl). – ChrisW

10

이것은 정의되지 않은 동작입니다. 자신의 책임하에 사용하십시오. 이은 (는) calling convention에서 사용중인 따라 달라집니다 작동 여부 Nasal Demons!

enter image description here

+0

이 이미지는 대단합니다. 여기에 정리 된 버전과 벡터 추적을 제공합니다. https://www.dropbox.com/sh/c0f5htyg46jcels/AABD9Qaw2JlhMAKCycAek-9ia?dl=0 – wilx

+0

롤. 고맙습니다.낙서하기를 좋아하는 딸에게 정의되지 않은 행동에 관한 이야기를 들려주었습니다. 그녀는 다음날이 편지를 보냈습니다. 그것에 대해 너무나 많이 사랑합니다. – EvilTeach

+0

다음은 JPG입니다. http://imgur.com/gallery/Zomm1zq/new – wilx

2

을 유발하는 소문이났다.

추천하지 않습니다.

3

함수 호출이 정의되지 않은 동작입니다.

(C99, 6.3.2.3p8) "[...] 변환 된 포인터가 유형이 뾰족 유형과 호환되지 않는 함수를 호출하는 경우 동작은 정의되지 않습니다." 정보 참고

함수 타입 있음 :

(C99, 6.2.5p20)은 "[...] 지정된 리턴 유형의 기능을 설명하는 기능 유형 특징 이다. 반환 유형 및 매개 변수의 수와 유형이 포함됩니다. "

관련 문제