Выберите функцию во время компиляции
-
08-07-2019 - |
Вопрос
в моем проекте на языке Си у меня есть пять разных функций (с одинаковым именем), которые реализуют один алгоритм, но по-разному.Во время компиляции мне нужно выбрать только одну из этих функций.Могу ли я реализовать это с помощью #define
и куча других #ifndef
?Есть ли лучшие способы сделать это?
Решение
Вероятно, более элегантным подходом было бы определить их с 5 разными именами (например, f1, f2, f3, f4, f5), но всегда вызывать функцию, используя одно и то же другое имя (например, f). Затем скомпилируйте что-нибудь вроде:
gcc -Df=f1
Это скомпилирует любые вызовы f () как вызов f1 ().
Другие советы
ДА.Все, что вы делаете, это указываете это в коде:
#if defined(FUNC1)
...func1 here
#elif defined(FUNC2)
...func2 here
...ect. ect.
#endif
А затем, когда вы компилируете, добавьте опцию gcc -DFUNCX, например:
gcc -DFUNC1 -o myprogram myfile.c
Затем вы можете выбрать, в какой функции выполнять компиляцию, изменив значение, введенное в параметр -D.Это очень распространенная практика.
У вас не может быть двух разных функций с одинаковым именем, определенных в одной единице перевода.
Итак, я думаю, у вас уже есть функции, разделенные между различными исходными файлами. Просто включите нужный файл при компиляции ... например, с помощью 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) { /* ... */ }
В Си это единственный способ, которым я знаю, как это делать. С ++ тебе повезет.
Если у вас есть источник для функций в отдельных файлах (для моего примера, в 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
строк.
Макросы ifndef кажутся единственной возможностью во время компиляции.
Вы можете попробовать использовать функцию ptrs во время выполнения.
Просто подумал, что вы можете создать каждую функцию в отдельном файле и связать соответствующую функцию, когда захотите. Никаких макросов, просто переключатель Makefile. Таким образом, вы сохраняете одну и ту же сигнатуру и решаете во время соединения, какую реализацию использовать. Ссылка algo1.o или ссылка algo2.o ...
Если бы я был тобой, у меня было бы 5 разных имен функций, а затем использовал бы оператор if, чтобы выяснить, какую из них вызывать во время выполнения.
C не имеет перегрузки (оператор или иным образом), поэтому другого способа сделать это нет. Боюсь, вы застряли с командами препроцессора.
если вы настаиваете на использовании C, вы можете использовать указатели на функции, но я бы посоветовал вам использовать C ++ и полиморфизм, это избавит вас от проблем:)