2010-01-07 3 views
6

이 형식의 함수 포인터를 캐스팅 할 수 있습니까?한 유형의 함수에 포인터를 추가 인수를 사용하는 다른 유형의 함수에 캐스트 할 수 있습니까?

void (*one)(int a) 

void (*two)(int a, int b) 

중 하나로 변환 한 다음 추가 인수를 사용하여 pointed-to 함수를 안전하게 호출 할 수 있습니까? 캐스팅 해? 나는 그러한 것들이 불법이라고 생각 했었고, 두 함수 유형 모두 호환되어야했다. (동일한 프로토 타입 - 동일한 반환 값, 동일한 매개 변수 목록을 의미합니다.)하지만 바로 이것이 GTK + 코드의이 비트가 수행하는 것으로 보이는 것입니다 (here에서 가져옴).

g_signal_connect_swapped(G_OBJECT(button), "clicked", 
         G_CALLBACK(gtk_widget_destroy), G_OBJECT(window)); 

" (또는 첫 번째 링크에서 사용 된 다른 예제를 보시면) 핸들러가 다음과 같이 선언 될 것으로 예상됩니다 :

void user_function(GtkButton *button, gpointer user_data); 

g_signal_connect_swapped()를 통해 핸들러를 등록 할 때, 위젯 포인터와 데이터 포인터 인수는 순서대로 바뀌므로 다음과 같이 선언해야합니다.

void user_function(gpointer user_data, GtkButton *button); 

여기에 문제가 있습니다. 콜백으로 등록 된 gtk_widget_destroy() 함수는 다음과 같이 프로토 타입 화됩니다.

void gtk_widget_destroy(GtkWidget *widget); 

단일 인수 만 사용합니다. 아마도 데이터 포인터 (GtkWindow)와 시그널 위젯 (GtkButton)에 대한 포인터가 바뀌기 때문에받는 유일한 인수는 윈도우 포인터가 될 것이고, 이후에 전달 될 버튼 포인터는 무시 될 것이다 . 몇몇 Googling은 인수를 전혀 사용하지 않는 gtk_main_quit() 같은 함수의 등록조차도 비슷한 예제를 보여줍니다.

이것이 표준 위반이라고 생각하는 것이 맞습니까? GTK + 개발자가이 모든 작업을 수행 할 수있는 몇 가지 법적 마법을 찾았습니까?

+0

Dupe : http://stackoverflow.com/questions/188839/function-pointer-cast-to-different-signature –

답변

2

C 호출 규칙을 사용하면 스택에서 인수를 정리하는 것이 호출자의 책임입니다. 따라서 호출자가 너무 많은 인수를 제공하면 문제가되지 않습니다. 추가 인수는 무시됩니다.

그렇습니다. 함수 포인터를 같은 인수와 다른 인수를 사용하여 캐스팅 할 수 있으며, 너무 많은 인수로 원래 함수를 호출하면 작동합니다.

+2

실제로, 나는 " C 호출 규칙 "을 참조하십시오. C 표준은이 표준을 정의하지 않으므로 컴파일러와 플랫폼에 따라 사용 규칙을 결정합니다. 그러나 * 대부분의 컴파일러/플랫폼에서는 사용자가 설명하는 호출 규칙을 사용합니다. – sleske

1

제 의견으로는 C89 표준은 상당히 혼란 스럽습니다. 지금까지 내가 아는 한, 그들이 그렇게, 아니 PARAM 사양과 기능 /에서 캐스팅 허용하지 않습니다

typedef void (*one)(int first); 
typedef void (*two)(int first, int second); 
typedef void (*empty)(); 

one src = something; 
two dst; 

/* Disallowed by C89 standards */ 
dst = (two) src; 

/* Not disallowed by C89 standards */ 
dst = (two) ((empty) src); 

을 마지막에 '컴파일러는 twoone에서 캐스팅 할 수 있어야합니다, 그래서 나는 돈 직접적인 던지기를 금지하는 이유를 보지 마십시오.

어쨌든 GTK +에서의 신호 처리는 뒤에서 어떤 dark magic을 사용하여 다른 인수 패턴을 가진 콜백을 관리하지만 이것은 다른 질문입니다.

1

이제 얼마나 멋진 지, 현재 GTK 튜토리얼을 통해 진행 중이며 똑같은 문제를 발견했습니다.

몇 가지 예를 시도한 다음 간단한 예제와 함께 What happens if I cast a function pointer, changing the number of parameters 질문을했습니다.

(위 내 질문에 대한 우수 답변과 질문 Function pointer cast to different signature의 대답에서 적응) 귀하의 질문에 대한 답변 :

  • 예,이 C 표준을 위반하는 것입니다. 함수 포인터를 호환되지 않는 형식의 함수 포인터로 캐스팅하는 경우 호출하기 전에 원래 형식 (호환 가능)으로 다시 캐스팅해야합니다. 다른 것은 정의되지 않은 동작입니다.
  • 그러나 실제로는 C 컴파일러, 특히 사용하는 호출 규칙에 따라 다릅니다. 가장 일반적인 호출 규칙 (적어도 i386)은 스택에 매개 변수를 역순으로 놓는 것입니다. 따라서 함수가 제공된 것보다 매개 변수가 적게 필요하면 나머지 매개 변수를 무시하고 첫 번째 매개 변수를 사용합니다. 당신이 원하는 것입니다. 이 은 다른 호출 규칙이있는 플랫폼에서 깨지므로이됩니다.

그래서 진짜 질문은 왜 GLib 개발자가 이렇게했는지입니다. 그러나 그것은 내가 추측하는 다른 질문입니다 ...

관련 문제