2015-03-27 2 views
1

У меня есть функция C с определенным числом аргументов (не функция varargs). Например:C - функция вызова с динамическим числом аргументов

void testfunction(int a, int b, int c); 

Эта функция является черным ящиком, поэтому я не могу ее изменить.

В основной функции у меня есть массив, содержащий все аргументы, которые я хочу передать своей «тестовой функции». Например:

void main() { 
    int args[] = {1, 2, 3}; 
    ... 
} 

Если предположить, что я не знаю заранее, что количество аргументов, что мой «функции теста» будет принимать (так как эта функция может меняться, в зависимости от функции, которую я хочу проверить), как можно ли вызвать «testfunction» с аргументами в массиве, динамически определенными?

У меня есть некоторый опыт в Ruby, это было бы эквивалентно

def test(a, b, c) 
    ... 
end 
array = [1,2,3] 
test(*array) 

Спасибо вам много!

+0

Для этого не существует стандартного способа C. Вам придётся прибегать к машинным трюкам сборки или иметь длинный переключатель для каждого количества аргументов, которые вы хотите поддержать. – 5gon12eder

+2

До тех пор, пока ваше соглашение о вызове - это очистка звонящего, вы можете вызвать функцию с большим количеством аргументов, чем она требуется/хочет. – EOF

+1

Может быть, мне что-то не хватает (если так, извините), но почему ваша тестовая функция не может принять указатель на массив и несколько аргументов? 'void testfunction (void * arrayPtr, int numArgs)'? – Mawg

ответ

0

Ну, вы не можете достичь именно того, чего хотите, но вы можете приблизиться, если у вас есть ограничение на количество аргументов, которые вы хотите перенести. Вы также потеряете защиту определенного типа. Вот как это сделать:

#include <stdio.h> 
#include <stdlib.h> 

typedef void (*tf_t)(); // `tf_t` can accept any number of arguments 

void tf1(int a) { printf("tf1: %d\n", a); } 
void tf2(int a, int b) { printf("tf2: %d, %d\n", a,b); } 
void tf3(int a, int b, int c) { printf("tf3: %d, %d, %d\n", a,b,c); } 

void call(tf_t tf, int args[], unsigned n) 
{ 
    switch (n) { 
    case 0: tf(); break; 
    case 1: tf(args[0]); break; 
    case 2: tf(args[0], args[1]); break; 
    case 3: tf(args[0], args[1], args[2]); break; 
    default: puts("Can't handle more than 3 arguments"); abort(); break; 
    } 
} 

int main() 
{ 
    int args[] = { 1, 2 }; 
    call(tf2, args, sizeof args/sizeof args[0]); 
    return 0; 
} 

Конечно, если вы передаете tf3 к call() он будет печатать мусор в качестве третьего числа, но это цена, которую вы платите.

В принципе, вы не должны делать такие вещи, так как может быть много проблем с вызовами конвенций, но на практике это, скорее всего, будет работать.

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