2015-12-06 23 views
2

我有一個函數的數組需要在運行時被分配來按順序調用。哪個函數指針進入了該點的編程確定,例如:Malloc函數指針數組

void ((drawFunctions*)(...))[0] = drawTriangle; 
... 
for(...) 
    drawFunctions[i](...); 

我想malloc函數指針數組,因爲我不知道,直到運行時多少會需要。你會如何做到這一點?

+0

http://stackoverflow.com/questions/5488608/how-define-an-array-of-function-pointers-in-c – Ashalynd

+1

所有的功能都採用相同的參數嗎? 「...」是否指示省略代碼,或者是否字面意思是「...」以指示它們是可變的? –

+0

你會更好地編輯你的問題,有真正的C99代碼,並避免你的'...' –

回答

4

一個類型定義可能會使得語法有點更愜意:

typedef void (*drawFunctionPointer)(void); 
drawFunctionPointer *drawFunctions = malloc(sizeof(drawFunctionPointer) * numFunctions); 
2

首先,在C99,一個variadic function應至少有一個第一非可變參數的參數(如printfconst char*fmt第一個參數)。請參閱stdarg(3)

然後,爲了便於閱讀,我將使用typedef來聲明函數簽名,例如,

typedef void drawfun_sigt (int, ...); 

聲明變量保持指針的指針數組:

drawfun_sigt** parr = NULL; 

分配它(和處理失敗):

size_t nbfun = somenumber(); 
parr = malloc(nbfun*sizeof(drawfun_sigt*)); 
if (!parr) { perror("malloc"); exit(EXIT_FAILURE); }; 

清除它(使行爲更可再現的,我不喜歡malloc -ed數組中的未初始化元素;但cmaster評論說,valgrind會發現這些錯誤);你也可以使用calloc代替malloc

memset (parr, 0, nbfun*sizeof(drawfun_sigt*)); 

然後填充適當

extern void drawfunfoo(int, ....); 
parr[0] = drawfunfoo; 

當然,也有很多方法可以讓一個函數的地址。在POSIX系統(特別是Linux的),你可以通過它的名稱中使用dlopen(3)dlsym(3)

甚至得到這樣一個地址動態如果你的函數指針有一個完全未知的簽名(即如果省略號...意味着什麼比可變參數函數其他您的問題),您應該使用libffi(或者,如果已知簽名集合,則使用函數指針的union)。請注意,C實現上的calling convention(和ABI)可能(並且通常會)決定使用不同簽名調用函數的不同方法。例如,用於Linux的x86-64 ABI需要可變參數函數和非可變參數函數以不同的方式調用,並在寄存器中傳遞一些形式參數(用於整數和浮點的不同寄存器)。

+0

如果你打算在malloc之後立即清零,那麼不要使用'calloc'的任何理由? – Mat

+0

因爲OP需要'malloc'。事實上,我更喜歡'calloc' –

+2

'malloc'似乎對我來說毫無意義,除非你實際使用這些零*,否則清零內存。讀取未寫入的分配部分始終是一個錯誤,並確保只有零才能讀取,可能僅用於掩蓋錯誤。更重要的是:如果你使用zero'ed內存分配*'valgrind'不會再發現這些錯誤*。如果沒有調零,它會報告使用未初始化的數據。通過調零,'valgrind'看到您在讀取之前主動初始化內存,所以它不會響起警報。所以,'calloc()'在避免錯誤方面真的是不合適的。 – cmaster