2012-11-18 20 views
5

可能重複:
Casting a function pointer to another type通過C中合法/定義的函數指針傳遞附加參數嗎?

假設我初始化與實際花費較少的參數則該函數指針定義的功能的函數指針,將功能仍然正確地執行,如果通過所述被叫函數指針?

我試圖與海灣合作委員會和它的工作如預期,但我不知道是否該行爲是跨編譯器/平臺上是一致的(我懷疑有些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否:要「保證」你想要什麼,你可能需要確保目標函數和函數指針都使用[cdecl調用約定](http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl )。 – ChrisW

10

這是未定義的行爲。使用風險自負。有傳聞導致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

3

函數調用是未定義的行爲。

(C99,6.3.2.3p8)「[...]」如果轉換的指針用於調用類型與指向類型不兼容的函數,則行爲是不確定的。

有關信息。注意,函數類型

(C99,6.2.5p20)「[...]描述了用指定的返回類型的函數的函數類型是 ,其特徵在於。其返回類型以及參數的數量和類型。「