2015-12-06 4 views
2

У меня есть набор функций, которые необходимо выделить во время выполнения, которые будут вызываться последовательно. Какие функции указатель идет в какой точке определяется программно, например .:Malloc массив указателей на функции

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

Я хочу таНос массив указателей на функции, потому что я не знаю, до времени выполнения, как будет нужно много. Как бы вы это сделали?

+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 должен иметь по крайней мере один первый не VARIADIC аргумент (как printf имеет const 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, но cmaster прокомментировал, что valgrind найдет эти ошибки); вы могли бы использовать calloc вместо malloc:

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

затем заполнить его соответствующим образом

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

Конечно, есть много способов, чтобы получить адрес функции. На POSIX систем (в частности, Linux) вы даже можете получить такой адрес динамически его имя с помощью dlopen(3) и dlsym(3)

Если указатели на функции имеют совершенно неизвестную подпись (т.е. если многоточие ... означает что-то другое, чем VARIADIC функция в ваш вопрос), вы должны использовать libffi (или, если набор сигнатур известен, используйте указатели функций union). Имейте в виду, что calling conventionABI) на вашей реализации C могут (и часто) диктуют разные способы вызова функций с другой подписью. Например, x86-64 ABI для Linux требует, чтобы переменные функции и невариантные функции вызывались по-разному и передавали некоторые формальные аргументы в регистры (разные регистры для integer и для плавающей запятой).

+0

Любые причины не использовать 'calloc', если вы собираетесь его обнулить сразу после malloc? – Mat

+0

Потому что OP хочет 'malloc'. Действительно, я предпочитаю 'calloc' –

+2

Нулевая память после' malloc' кажется мне совершенно бессмысленной *, если вы на самом деле не используете эти нули *. Чтение частей распределения, которое вы не написали, всегда является ошибкой, и обеспечение того, что у вас есть только нули для чтения, может служить только для маскировки ошибки. Что еще более важно: если вы используете нулевые выделения памяти, '' valgrind' больше не найдет эти ошибки *. Без обнуления он будет сообщать об использовании неинициализированных данных. При обнулении 'valgrind' видит, что вы активно инициализируете память перед чтением, поэтому она не будет вызывать тревогу. Таким образом, 'calloc()' на самом деле является противопоказанием для предотвращения ошибок. – cmaster

Смежные вопросы