我可以重新定义一个函数或检查它是否存在?
我有一个关于(重新)定义函数的问题。 我的目标是有一个脚本,我可以选择定义一个函数。 像这样:
void func(){} int main(){ if (func)func(); }
没有这个function,只需:
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() { ... }
即使在另一个.c文件或库中定义了func()
这也可以工作。
我想是这样的。 没有多少使用函数指针,所以我的语法可能略有错误。
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
语句完成。 如果你想要一个if语句来控制你的程序流,只需使用它,而不必费心去尝试重命名函数或使用函数指针等。
介绍
我猜你正试图这样做:
- 两个模块,
ao
和bo
-
bo
包含void foo()
的定义 - 只有当
bo
也链接到最终的可执行文件时,ao
才会调用void foo()
。
这对于“插件”系统可能很有用。
变化1
您可以使用函数指针进行模拟。 我不知道足够的C用适当的C代码写这个,但伪代码看起来像这样:
啊
extern collectionOfFuncPtrs_t list; int addFuncPtr();
AC
#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);
CC
#include "ah" void ayb() { /* ... */ } static int dummy = addFuncPtr(&ayb);
结论
现在,您可以根据需要链接bo
和/或co
,而int main()
只会调用bar()
和/或ayb()
如果存在)。
变化2
尝试使用此主题的变体,如果它看起来可能对您有用。 特别是,如果您只有特定数量的条件定义函数,则可以使用一堆单独的函数指针而不是某些列表:
啊
extern fptr_t bar_ptr, ayb_ptr;
AC
#include "ah" int main() { if (bar_ptr) bar_ptr(); if (ayb_ptr) ayb_ptr(); }
公元前
#include "ah" void bar() { /* ... */ } fptr_t bar_ptr = &bar;
b_dummy.c
#include "ah" fptr_t bar_ptr = 0;
CC
#include "ah" void ayb() { /* ... */ } fptr_t ayb_ptr = &ayb;
c_dummy.c
#include "ah" fptr_t ayb_ptr = 0;
结论
现在要么链接bo
或b_dummy.o
; 并链接co
或c_dummy.o
。
无论如何,我希望你能得到一般的想法……!
Bootnote
在C ++中,这很容易,您可以使用std::map
和构造函数轻松编写模块注册系统。
在C? 只能使用其他答案中所述的预处理器。
C不是像Python这样的动态语言。
在C中做我认为你要问的正确方法是使用函数指针 。 您可以获取函数的地址,将其分配给变量,将其测试为nil等。但是,普通的旧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中有效,如果使用-fms-extensions
标志,则在clang中-fms-extensions
。