Как применить сигнатуры функций для набора объявлений функций в C? - PullRequest
4 голосов
/ 09 октября 2008

Я хочу убедиться, что набор функций имеет одинаковую сигнатуру в некотором C-коде. В идеале я мог бы определить новый тип, который описывает возвращаемое значение и аргументы функции, а затем объявить мой набор функций, используя этот новый тип.

Кроме того, есть ли способ указать значения по умолчанию для аргументов этой функции typedef?

Ответы [ 5 ]

13 голосов
/ 09 октября 2008
/* define a typedef for function_t - functions that return void */
/*      and take an  int and char parameter */

typedef void function_t( int param1, char param2);

/* declare some functions that use that signature */

function_t foo;
function_t bar;

Теперь при определении функций будет ошибка, если они не используют ту же сигнатуру, что и в typedef.

void foo( int x, char c)
{
    /* do some stuff */

    return;
}

/* this will result in a compiler error */
int bar( int x, char c)
{
    /* do some stuff */

    return 1;
}

Что касается вашего нового вопроса (добавлено 20 октября 08): «Кроме того, есть ли способ указать значения по умолчанию для аргументов этой функции typedef?»

Нет, нет способа добавить параметры по умолчанию в typedef. Конечно, нет в C, который вообще не поддерживает параметры по умолчанию. Даже в C ++ вы не можете сделать это, потому что значение параметра по умолчанию не является частью типа. Фактически, класс, который переопределяет виртуальный метод из базового класса, может указать другое значение для параметра по умолчанию (или даже полностью удалить значение по умолчанию) - однако, это не следует делать в общем, поскольку это просто вызовет путаницу (http://www.gotw.ca/gotw/005.htm).

Если вы используете C ++, вы можете получить желаемое поведение, используя одно из (или комбинацию) следующего:

  • абстрактные базовые классы
  • перегрузки
  • шаблонные функции
  • макросы

Но было бы трудно что-то предложить, не зная больше подробностей о том, что именно вы пытаетесь достичь. И я думаю, что вполне вероятно, что результат будет довольно хакерским.

0 голосов
/ 12 октября 2011

Вот пример создания списка функций, сопоставленных с простой строкой.

Сначала введите typedefs:

typedef GenList *(*DBLISTLOADER)(Database *pDB, char *quellCD, char *profilName);
typedef ObjDescription *(*DBCOLUMNLOADER)();

typedef struct dbinfo
{
    char *dbName;
    DBLISTLOADER dbListLoader;
    DBCOLUMNLOADER dbColumnLoader;
    char *options;
} DBINFO;

Тогда таблица сопоставления:

DBINFO dbInfoList[] =
{
   { "SRCDOC",   loadSRCDOC,      colSRCDOC,      "q"  },
   { "PRF_CD",   loadPRF_CD,      colPRF_CD,      ""   },
   { "MEDIA",    loadMEDIA,       colMEDIA,       ""   },

   { NULL,       NULL,            NULL }
};

Теперь, чтобы найти функцию из этой таблицы и вызвать ее:

while (dbInfoList[i].dbName != NULL)
{
    if (strcmp(dbInfoList[i].dbName, szDatabase) == 0)
    {
        return (dbInfoList[i].dbListLoader)(pDB, quellCD, profilName);
    }

    i++;
}

Извините, если это немного "сырой". Вставлено прямо из нашего кода; -)

0 голосов
/ 09 октября 2008

Вы не можете реально помешать кому-либо сделать функцию подписью. Но вы можете контролировать то, что вы будете называть. Поэтому я предполагаю, что это то, что вы хотите.

У функции, которая будет вызывать произвольные функции, взять указатель на функцию в качестве параметра. Поскольку вы упомянули typedef, вы можете определить typedef ранее в программе, например так:

Предположим, вам нужны только функции подписи "unsigned short id_for_allowed_functions (int x, char * y)":

typedef unsigned short (*id_for_allowed_functions)(int, char*);

Тогда ваша вызывающая функция:

void calling_function (id_for_allowed_function x) { (*x)(3, "bla"); }

И для того, чтобы предоставить ему функцию foo:

unsigned short foo(int x, char* y) { /* ... */ }
calling_function(&foo);
0 голосов
/ 09 октября 2008

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

typedef void (*MethodSig)(int, int);

static MethodSig x[] = { fnA, fnB, ... };

Или используйте макрос для объявления сигнатуры функции

#define MyFunc(X)  void X(int a, int b)

Таким образом, они все будут одинаковыми.

0 голосов
/ 09 октября 2008

Это похоже на то, как работает указатель на функцию:

 // Declaration of function with int arg returning int
 typedef int (*CALLBACK)(int);

 //Definition
 int myFunc(int arg)
 {
     return 0;
 }

 // Function pointer usage
 CALLBACK pFunc = myFunc;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...