Как создать функцию в С, которая может принимать как 2 аргумента, так и 3?
Есть функция bar(const char *a, struct my_struct1 b, struct my_struct2 c), как сделать так, чтобы эту функцию можно было вызывать от двух аргументов, то есть так: bar(const char *a, struct my_struct1 b)?
Ответы (2 шт):
Можно попробовать библиотеку с переменным количеством аргументов. Но в этом случае определить дали аргумент или нет можно только с помощью передачи нулевого указателя.
// -Wall -Wextra -Wpedantic --std=c11 -Winline
#include <stdarg.h>
typedef int calc_result ;
typedef int(*calc_function)(int) ;
int calc_evaluate(const char *buffer, calc_result *res, ... /*calc_function functions[]*/){
va_list arguments;
va_start ( arguments, res );
calc_function * functions = va_arg ( arguments, calc_function * );
if ( functions )
/* если аргумент есть */ ;
else
/* если указатель нулевой */ ;
va_end ( arguments );
}
calc_evaluate("",&res,(calc_function*)0);
А если хочется два варианта : без третьего указателя или с третим нулевым, то и приходим опять к началу вопроса.
В одиннадцатом стандарте можно определить функции с одним именем но с разным типом аргумента.
int calc_evaluate(const char *buffer, calc_result *res,
calc_function functions[]);
int calc_evaluatev(const char *buffer, calc_result *res);
#define calc_evaluate2t(X,Y,Z) \
_Generic( (Z), \
calc_function * : calc_evaluate(X,Y,Z) , \
int * : calc_evaluatev(X,Y) )
calc_evaluate2t("",&res,(int*)0);
calc_evaluate2t("",&res,functions);
Но к макросу и к Generic нужно предложить третий аргумент чтобы определить тип. Опять пришли к тому-же.
Есть способ передавать аргументы в функцию с помощью одной структуры разного типа. Но эти типы нужно объявлять и писанины будет много.
typedef
struct {
const char *buffer;
calc_result *res;
} args2 ;
typedef
struct {
const char *buffer;
calc_result *res;
calc_function * functions ;
} args3 ;
int calc_evaluate2(args2);
int calc_evaluate3(args3);
#define calc_evaluatet(X) \
_Generic( (X), \
args2: calc_evaluate2, \
args3: calc_evaluate3 )(X)
calc_evaluatet(((args2){"",&res}));
calc_evaluatet(((args3){"",&res,functions}));
Имя типа структур нужно задавать вручную и писанины опять много лишней.
Не проще ли вам сделать две функции с разным именем?
int calc_evaluateN(const char *buffer, calc_result *res) ;
int calc_evaluateF(const char *buffer, calc_result *res,
calc_function functions[]);