Portnov... Sorry...
Как много написали, попробую обдумать... Так, подумал. Обижаться в любом случае не буду :-)
(Portnov) писал(а):Тогда только обязательно нужно последним указателем в передаваемом массиве ставить NULL.
Об этом я уже написал, вы не заметили, но:
Код: Выделить всё
int void_mas_length(void ** p) {
int n = 0;
while (p[n++] != NULL)
;
return n;
}
Эта функция не будет правильно отдавать длинну массива, она споткнётся на первом же нуле в массиве, кроме того - некоторые функции принимают аргументы, значением которых может быть NULL. Особенно под Win, а мне нужен кроссплатформенный код. Это, кстати, и довод в пользу С. Ну а что касается С++, то мне классы не нужны просто, достаточно структур и модульности.
(Portnov) писал(а):А вообще, такое сложное решение обычно указывает на то, что вышестоящая задача решается неправильно. Т.е., в данном случае, скорее всего, решается не та задача.
Решение-то уже есть, я просто решил узнать - нельзя ли лучше. Да и задачу вроде выбрал адекватную ))
(NickLion) писал(а):Что есть f/_f_? Почему не вызывать напрямую?
??? Как бы бывают функции, определенные только по указателю, для таких функций вызов (*f)(...) и есть вызов на прямую. Или я не прав?
drBarty, если сделать аргументы связным списком, то и их придётся мыслить как сишный объект.
Код: Выделить всё
typedef struct arg_list {
void * arg;
int type;
struct arg_list * next;
} object_argu;
object_argu * initialize_argu (void ** arg, int * type, int n) {
object_argu * argu;
if (n > 0) {
argu = (object_argu *) malloc (sizeof (object_argu));
argu -> arg = arg;
argu -> type = type;
argu -> next = initialize_argu(*arg++, *type++, n - 1);
return argu;
} else {
argu = (object_argu *) malloc (sizeof (object_argu));
argu -> arg = arg;
argu -> type = type;
argu -> next = NULL;
return argu;
}
}
int length_argu (object_argu * argu) {
if (argu -> next == NULL)
return 1;
else
return length_argu(argu -> next) + 1;
}
void * get_arg (object_argu * argu, int i) {
if (i == 0)
return argu -> arg;
else
return get_arg(argu -> next, i - 1);
}
// ...
// тут, опять таки, достаем указатель на __g__
//
n = length_argu (argu);
switch (n) {
case 0: rusult = (* __g__)(); break;
case 1: rusult = (* __g__)(get_arg(argu, 0)); break;
case 2: rusult = (* __g__)(get_arg(argu, 0), get_arg(argu, 1)); break;
case 3: rusult = (* __g__)(get_arg(argu, 0), get_arg(argu, 1), get_arg(argu, 2)); break;
case 4: rusult = (* __g__)(get_arg(argu, 0), get_arg(argu, 1), get_arg(argu, 2), get_arg(argu, 3)); break;
case 5: rusult = (* __g__)(get_arg(argu, 0), get_arg(argu, 1), get_arg(argu, 2), get_arg(argu, 3), get_arg(argu, 4)); break;
// ...
// ...
Вроде от необходимости указывать кол-во аргументов избавились, но их количество всё равно ограничено сверху (в switch).
Вот если бы в Си можно было написать (* f)(void ** args) а сколько там аргументов решал бы компилятор. Правдо не ясно, как определить последний эллемент - NULL то не подходит. Представьте себе, что в стандарте Си написано: "Использовать число 566345486344 в языке нельзя, потому что оно используется для указания конца списка аргументов функции". :-)))