我有一个关于(重新)定义函数的问题。我的目标是创建一个脚本,在其中可以选择是否定义函数。 像这样:
void func(){}
int main(){
if (func)func();
}
不使用函数,只需:
int main(){
if (func)func();
}
有人有想法吗?
我有一个关于(重新)定义函数的问题。我的目标是创建一个脚本,在其中可以选择是否定义函数。 像这样:
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 文件或库中定义,这个方法仍然有效。
#pragma weak
。http://en.wikipedia.org/wiki/Weak_symbol - JABif (func)
,除非在同一编译单元中实际存在定义,因为它不知道是否会由其他编译单元或共享库提供定义等。 - bdonlan我认为应该是这样的。我没有太多使用函数指针的经验,所以语法可能略有错误。
void func()
{
#define FUNC_PRESENT
// code
}
void (*funcptr)();
#ifdef FUNC_PRESENT
funcptr = func;
#else
funcptr = NULL;
#endif
int main()
{
if (funcptr)
funcptr();
}
#define
并不是你想象中的那样。以#开头的行会在编译开始前按顺序扫描并从源文件中删除,因此当你到达#ifdef
时,FUNC_PRESENT将始终被定义。而在函数定义中放置#define FUNC_PRESENT
没有任何有用的意义。 - Rag#define
定义放在函数定义的语法内部。我知道您试图将代码捆绑在一起,以便移动时更少出错,但这可能会让某些程序员误解 PP 宏定义只在调用 func()
时才会发生。[编辑:或者会让程序员误认为这是您的想法,就像上面的 Brian 一样] - Lightness Races in Orbit#define
放在函数定义内部,这样当函数定义从代码/头文件中移除时,#include
的代码会自动带走#define
。 - JAB使用函数指针,根据运行时条件动态设置它们,并检查空指针或将它们包装在方法中,让方法替你进行检查。
这是我所能想到的C语言中的唯一选项。
在C++中,您可以结合模板和DLL在运行时动态定义。
你能够“选择是否定义一个函数”唯一的方法是使用C预处理器指令。例如:
#ifdef some_name
void func() {
do_whatever();
}
#else
//the else part is optional
#endif
要设置这些“变量”,您可以使用#define some_name
问题是,所有这些都需要在编译时(实际上是在之前)完成,因此不能像您的示例中那样使用if
语句进行操作。如果您想要一个if语句来控制程序流程,请直接使用它,不必费心尝试重命名函数或使用函数指针等。
我猜你正在尝试做这个:
a.o
和 b.o
b.o
包含了 void foo()
的定义a.o
只有在最终可执行文件中链接了 b.o
才会调用 void foo()
。这对于一个“插件”系统可能很有用。
您可以使用函数指针来模拟它。我不太懂 C 语言,无法编写出符合规范的代码,但伪代码如下:
extern collectionOfFuncPtrs_t list;
int addFuncPtr();
#include "a.h"
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 "a.h"
void bar() { /* ... */ }
static int dummy = addFuncPtr(&bar);
#include "a.h"
void ayb() { /* ... */ }
static int dummy = addFuncPtr(&ayb);
现在,您可以根据需要链接b.o
和/或c.o
,并且int main()
仅在它们存在时调用bar()
和/或ayb()
。
如果这个主题看起来对你有用,可以尝试一些变化。特别是,如果你只有一些有条件定义的函数,你可以使用一堆单独的函数指针而不是一些列表:
extern fptr_t bar_ptr, ayb_ptr;
#include "a.h"
int main() {
if (bar_ptr)
bar_ptr();
if (ayb_ptr)
ayb_ptr();
}
#include "a.h"
void bar() { /* ... */ }
fptr_t bar_ptr = &bar;
#include "a.h"
fptr_t bar_ptr = 0;
#include "a.h"
void ayb() { /* ... */ }
fptr_t ayb_ptr = &ayb;
#include "a.h"
fptr_t ayb_ptr = 0;
现在链接b.o
或b_dummy.o
;以及链接c.o
或c_dummy.o
。
希望你至少能够理解大意...!
在C++中,您可以使用std::map
和构造函数轻松编写模块注册系统,这使得这个过程变得容易得多。
static int dummy = addFuncPtr(&bar);
和 fptr_t bar_ptr = &bar;
这样的东西在 C 中会变成 static int dummy = addFuncPtr(bar);
和 fptr_t bar_ptr = bar;
,因为函数的处理方式不同。 - JAB&lol
格式使用它,但这可能是因为在你不知道它是实际的函数名称还是指向一个函数的指针的情况下,在某些情况下,如果不小心,你可能会出现段错误(http://codepad.org/SnmFE025)。 (这很可能是在一个函数将另一个函数作为其参数之一的情况下出现问题,因此你可以传递函数名称或函数指针。) - JAB用C语言?只能使用预处理器,如其他答案所述。
C语言不像Python一样是一种动态语言。
如果我理解你的问题正确,C语言中正确的做法是使用函数指针。你可以获取一个函数的地址,将其赋值给一个变量,测试它是否为空等等。然而,纯粹的C语言并不是一种非常动态的语言;你可能最好使用另一种语言。
如果您不介意使用编译器特定的扩展,您可以使用__if_exists
:
#include <iostream>
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。