У меня вопрос о (пере) определяющих функциях. Моя цель – иметь скрипт, где я могу выбрать функцию или нет. Как это:
void func(){} int main(){ if (func)func(); }
И без функции, просто:
int main(){ if (func)func(); }
У кого-нибудь есть идея?
Вы можете сделать это в GCC, используя расширение слабого атрибута функции:
void func() __attribute__((weak)); // weak declaration must always be present int main() { if (func) func(); // ... } // optional definition: void func() { ... }
Это работает, даже если func()
определен в другом .c файле или в библиотеке.
Что-то вроде этого, я думаю. Не использовали указатели функций много, поэтому я, возможно, немного изменил синтаксис.
void func() { #define FUNC_PRESENT // code } void (*funcptr)(); #ifdef FUNC_PRESENT funcptr = func; #else funcptr = NULL; #endif int main() { if (funcptr) funcptr(); }
Используйте указатели функций, динамически устанавливайте их на основе условий выполнения и проверяйте нулевые указатели или оберните их в методы, которые проверяют вас.
Только вариант в CI может придумать.
В C ++ вы можете комбинировать шаблоны и библиотеки DLL для динамического определения во время выполнения.
На самом деле единственный способ, которым вы можете «выбрать функцию или нет», – это директивы препроцессора C. Например:
#ifdef some_name void func() { do_whatever(); } #else //the else part is optional #endif
Чтобы установить эти «переменные», вы используете #define some_name
Проблема в том, что все это нужно делать во время компиляции (до этого, на самом деле), поэтому это невозможно сделать с помощью оператора if
подобного вашему примеру. Если вы хотите, чтобы оператор if контролировал stream вашей программы, просто используйте его и не беспокойтесь при попытке переименовать функции или с помощью указателей функций или чего-то еще.
Я предполагаю, что вы пытаетесь это сделать:
ao
и bo
bo
содержит определение для void foo()
ao
вызывает void foo()
только в том случае, если bo
также связан с окончательным исполняемым файлом. Это может быть полезно для системы «плагин».
Вы можете имитировать его с помощью указателей функций. Я не знаю достаточно C, чтобы написать это в правильном C-коде, но псевдокод выглядит так:
extern collectionOfFuncPtrs_t list; int addFuncPtr();
#include "ah" collectionOfFuncPtrs_t list; int addFuncPtr(FuncPtr p) { - add func ptr to list - return 0 } int main() { - loop through list of function pointers - call functions through them }
#include "ah" void bar() { /* ... */ } static int dummy = addFuncPtr(&bar);
#include "ah" void ayb() { /* ... */ } static int dummy = addFuncPtr(&ayb);
Теперь вы можете связать в bo
и / или co
по своему усмотрению, и int main()
будет только вызывать bar()
и / или ayb()
если они существуют.
Поэкспериментируйте с вариантами этой темы, если она выглядит так, как будто она вам полезна. В частности, если у вас есть только определенное количество условно определенных функций, вы можете использовать кучу отдельных указателей на функции, а не какой-то список:
extern fptr_t bar_ptr, ayb_ptr;
#include "ah" int main() { if (bar_ptr) bar_ptr(); if (ayb_ptr) ayb_ptr(); }
#include "ah" void bar() { /* ... */ } fptr_t bar_ptr = &bar;
#include "ah" fptr_t bar_ptr = 0;
#include "ah" void ayb() { /* ... */ } fptr_t ayb_ptr = &ayb;
#include "ah" fptr_t ayb_ptr = 0;
Теперь либо ссылку bo
либо b_dummy.o
; и либо ссылку co
либо c_dummy.o
.
Во всяком случае, я надеюсь, что ты получишь общую идею …!
Это намного проще на C ++, где вы можете легко писать систему регистрации модhive с помощью std::map
s и конструкторов.
В C? Только используя препроцессор, как указано в других ответах.
C не является динамическим языком, например, Python.
Правильный способ сделать то, о чем я думаю, что вы спрашиваете на C, – использовать указатели на функции . Вы можете взять адрес функции, назначить ее переменной, проверить ее на нуль и т. Д. Однако простой старый C не является очень динамичным языком; вам может быть лучше использовать другой язык.
если вы не возражаете против специального расширения компилятора, вы можете использовать __if_exists
:
#include using namespace std; // uncomment the following, and it'll still work void maybeFunc(){ cout << "running maybe" << endl; } int main(){ cout << "hi!" << endl; __if_exists(maybeFunc) cout << "maybe exists!" << endl; maybeFunc(); } }
это работает в msvc по умолчанию и в clang, если вы используете флаг -fms-extensions
.