Выберите функцию во время компиляции - PullRequest
1 голос
/ 29 октября 2009

в моем C-проекте у меня есть пять разных функций (с одинаковым именем), которые реализуют один алгоритм, но по-разному. Во время компиляции мне нужно выбрать только одну из этих функций. Могу ли я реализовать это, используя #define и кучу #ifndef? Есть ли лучшие способы сделать это?

Ответы [ 9 ]

15 голосов
/ 29 октября 2009

Вероятно, более элегантным подходом было бы определить их с 5 разными именами (например, f1, f2, f3, f4, f5), но всегда вызывать функцию, используя одно и то же другое имя (например, f). Затем скомпилируйте что-нибудь вроде:

gcc -Df=f1

Это скомпилирует любые вызовы f () как вызовы f1 ().

5 голосов
/ 29 октября 2009

Да. Что вы делаете, это сказать это в коде:

#if defined(FUNC1)
    ...func1 here
#elif defined(FUNC2)
    ...func2 here
...ect. ect.
#endif

А затем при компиляции добавьте опцию gcc -DFUNCX, например:

gcc -DFUNC1 -o myprogram myfile.c

Затем вы можете выбрать, какую функцию компилировать, изменив значение, указанное в параметре -D. Это очень распространенная практика.

3 голосов
/ 29 октября 2009

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

Так что, я думаю, у вас уже есть функции, разделенные между различными исходными файлами. Просто включите нужный файл при компиляции ... например, с помощью gcc

gcc -o testsort main.c bubble.c
gcc -o testsort main.c merge.c
gcc -o testsort main.c radix.c

Где любой из bubble.c, merge.c, radix.c (и другие) имеет функцию с таким же именем:

int sort(int *data, size_t len) { /* ... */ }
1 голос
/ 29 октября 2009

Если у вас есть источник для функций в отдельных файлах (для моего примера, в f1.c и f2.c), то эта схема работает:

$ cat so.c
#define STRINGIZER(x) #x
#define HEADER(x) STRINGIZER(x)

#include HEADER(SOURCE)

int main(void)
{
    return(function());
}
$ cat f1.c
static int function(void)
{
    return(1);
}
$ cat f2.c
static int function(void)
{
    return(2);
}
$

Тогда я могу скомпилировать так:

$ gcc -DSOURCE=f1.c -o so1 so.c
$ gcc -DSOURCE=f2.c -o so2 so.c

Обратите внимание на использование оператора stringize и танца с двойным макросом - это стандартная идиома для препроцессора Standard C. Это позволяет мне не помещать кавычки в командную строку компилятора C; подумайте, насколько сложнее было бы использовать, если бы вам пришлось написать:

$ gxx -DSOURCE='"f1.c"' -o so1.c

Результаты запуска so1 и so2 были:

$ ./so1; echo $?
1
$ ./so2; echo $?
2
$

Здесь показан альтернативный способ достижения желаемого результата без каких-либо #ifdef строк.

1 голос
/ 29 октября 2009

В Си это единственный способ, которым я знаю, как это делать. С ++ тебе повезет.

0 голосов
/ 25 июля 2010

если вы должны настаивать на использовании C, вы можете использовать указатели на функции, но я бы посоветовал вам использовать C ++ и полиморфизм, это избавит вас от проблем:)

0 голосов
/ 29 октября 2009

C не имеет перегрузки (оператор или иным образом), поэтому другого способа сделать это нет. Боюсь, вы застряли с командами препроцессора.

0 голосов
/ 29 октября 2009

на вашем месте у меня было бы 5 разных имен функций, затем используйте оператор if, чтобы выяснить, какую из них вызывать во время выполнения.

0 голосов
/ 29 октября 2009

Макросы ifndef кажутся единственной возможностью во время компиляции.

Вы можете попробовать использовать функцию ptrs во время выполнения.

Просто подумал, что вы можете создать каждую функцию в отдельном файле и связать соответствующую функцию, когда захотите. Никаких макросов, просто переключатель Makefile. Таким образом, вы сохраняете одну и ту же сигнатуру и решаете во время соединения, какую реализацию использовать. Ссылка algo1.o или ссылка algo2.o ...

...