我可以重新定义一个函数或检查它是否存在?

时间:2011-08-02 18:28:36

标签: c function

我有一个关于(重新)定义函数的问题。我的目标是有一个脚本,我可以选择定义一个函数。 像这样:

void func(){}

int main(){
   if (func)func();
}

没有这个功能,只需:

int main(){
   if (func)func();
}

有人有想法吗?

8 个答案:

答案 0 :(得分:16)

您可以使用其弱函数属性扩展名在GCC中执行此操作:

void func() __attribute__((weak)); // weak declaration must always be present

int main() {
  if (func) func();
  // ...
}

// optional definition:
void func() { ... }

即使在另一个.c文件或库中定义了func(),这仍然有效。

答案 1 :(得分:5)

我认为这样的事情。没有多少使用函数指针,所以我的语法可能略有错误。

  void func()
  {
#define FUNC_PRESENT
      // code
  }

  void (*funcptr)();

#ifdef FUNC_PRESENT
      funcptr = func;
#else
      funcptr = NULL;
#endif

  int main()
  {
      if (funcptr)
          funcptr();
  }

答案 2 :(得分:4)

使用函数指针,根据运行时条件动态设置它们,并检查空指针或将它们包装在为您检查的方法中。

C中我只能考虑选项。

在C ++中,您可以组合模板和DLL以在运行时动态定义。

答案 3 :(得分:3)

您可以“选择是否定义函数”的唯一方法是使用C预处理程序指令。例如:

#ifdef some_name
void func() {
    do_whatever();
}
#else
  //the else part is optional
#endif

要设置这些“变量”,请使用#define some_name

麻烦的是,所有这些都需要在编译时完成(在此之前,实际上),所以不能像你的例子那样使用if语句来完成。如果你想要一个if语句来控制你的程序流程,只需使用它,不要试图重命名函数或使用函数指针等。

答案 4 :(得分:1)

简介

我猜你正在尝试这样做:

  • 两个模块,a.ob.o
  • b.o包含void foo()
  • 的定义 如果a.o也链接到最终的可执行文件,则
  • void foo()仅调用b.o

这对于“插件”系统非常有用。


变体1

您可以使用函数指针进行模拟。我不知道足够的C用适当的C代码写这个,但伪代码看起来像这样:

A.H

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
}

b.c

#include "a.h"

void bar() { /* ... */ }

static int dummy = addFuncPtr(&bar);

C.C

#include "a.h"

void ayb() { /* ... */ }

static int dummy = addFuncPtr(&ayb);

结论

现在,您可以根据需要链接到b.o和/或c.oint main()只会调用bar()和/或ayb()存在。


变体2

尝试使用此主题的变体,如果它看起来可能对您有用。特别是,如果你只有一个特定数量的条件定义函数,你可以使用一堆单独的函数指针而不是一些列表:

A.H

extern fptr_t bar_ptr, ayb_ptr;

交流转换器

#include "a.h"

int main() {
   if (bar_ptr)
      bar_ptr();
   if (ayb_ptr)
      ayb_ptr();
}

b.c

#include "a.h"

void bar() { /* ... */ }

fptr_t bar_ptr = &bar;

b_dummy.c

#include "a.h"
fptr_t bar_ptr = 0;

C.C

#include "a.h"

void ayb() { /* ... */ }

fptr_t ayb_ptr = &ayb;

c_dummy.c

#include "a.h"
fptr_t ayb_ptr = 0;

结论

现在链接b.ob_dummy.o;并链接c.oc_dummy.o

我希望你能得到一般的想法,无论如何......!


Bootnote

在C ++中,这是 lot 更容易,您可以使用std::map和构造函数轻松编写模块注册系统。

答案 5 :(得分:0)

在C?只能使用其他答案中所述的预处理器。

C不是一种动态语言,比如Python。

答案 6 :(得分:0)

我认为您在C中提出的问题的正确方法是使用function pointers。您可以获取函数的地址,将其分配给变量,将其测试为nil等。但是,普通的旧C不是一种非常动态的语言;你可能最好使用不同的语言。

答案 7 :(得分:0)

如果您不介意编译器特定的扩展程序,可以使用AdminUserGlobalSignOut

__if_exists

默认情况下在msvc中有效,如果使用#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(); } } 标志,则在clang中有效。