是否可以交换C函数?

想看看是否有人知道它是否可以交换C函数……?

void swap2(int(*a)(int), int(*b)(int)) { int(*temp)(int) = a; *a = *b; *b = temp; // Gives 'Non-object type 'int (int)' is not assignable } swap2(&funcA, &funcB); 

编辑

关于意图的更多数据 – 下面提供了一些答案,它们可以使用typedef创建函数ptr,将它们指向函数并切换它们,从而可以成功调用新交换的ptrs。

但是在交换后以原始名称调用函数显示没有变化。 基本上我正在寻找相当于objc“swizzle”的交流。

我开始认为这是不可能的,因为c完全没有reflection,并且需要实际修改二进制本身(显然不可行)。 d:

欢迎评论。

如果您使用如下所示的函数指针,则为是

 typedef int (*func_pt)(int); func_pt a, b; void swap(func_pt * a, func_pt * b) { func_pt tmp = *b; *b = *a; *a = tmp; } swap(&a, &b); 

或者你这样使用它,我认为不是:

 int test1(int a) { return a; } int test2(int b) { return b; } swap(&test1, &test2); 

完整的编译工作程序

 #include  #include  typedef int (* func_pt)(int); func_pt a, b; int test1(int a) { printf("test1\n"); return 1; } int test2(int a) { printf("test2\n"); return 2; } void swap(func_pt * a, func_pt * b) { func_pt tmp = *b; *b = *a; *a = tmp; } int main(void) { a = &test1; b = &test2; printf("before\n"); a(1); b(1); swap(&a, &b); printf("after\n"); a(1); b(2); return 0; } 

输出:

 before test1 test2 after test2 test1 

有些人不会自己尝试,只是说它荒谬。所以我举个例子。

我很确定你需要指针指向交换指针的函数指针,不是吗? 这种类型的交换function交换值; 你真的想要处理地址。 示例函数调用不会真正起作用,因为C不会将函数视为第一类变量,因此您无法直接交换函数; 您需要使用指针来处理地址,因为地址可以交换:

 void swap2(int(**a)(int), int(**b)(int)) { int(*temp)(int) = *a; *a = *b; *b = *temp; } int(*func1)(int) = &foo; int(*func2)(int) = &bar; swap2(&func1, &func2); 

您的代码在分配时会给出“无效左值”之类的错误。 正如我在您的代码中看到的那样,您正在尝试交换指针而不更改其值,因此请查看下面的解决方案。

 void swap2(int(**a)(int), int(**b)(int)) { int(*temp)(int) = *a; *a = *b; *b = temp; } int main(){ int(*temp1)(int) = &funcA; int(*temp2)(int) = &funcB; swap2(&temp1,&temp2); } 

是的你可以。 认为一个函数指针只是一个内存地址,单个requeriment是:你将保持这样的地址需要是可变的。 比方说, int (*foo)()并不是真正指向foo指向的地方。 可能是printf()fopen()

虽然主题询问交换function,但实际上你想要模仿swizzle所做的事情。 这只是意味着您希望能够调用相同的函数名称,但让它做一些不同的事情。

仅指针解决方案不会为您提供该行为。 如果这对您不重要,那么您应该采用仅提供的function指针之一。 如果它对你重要,那么你需要引入一层抽象。 抽象可以使用引擎盖下的函数指针(尽管还有其他解决方案)。

此接口的用户的API将是:

 /* API to initialize */ void abstract_func_init (); /* API to manipulate abstract functions */ typedef int abstract_func_type (); abstract_func_type * abstract_func_get (abstract_func_type *key); int abstract_func_set (abstract_func_type *key, abstract_func_type *behavior); /* the abstract functions */ extern int foo (); extern int bar (); 

这种界面的实现可能如下所示:

 static void insert (abstract_func_type *key, abstract_func_type **behavior) { /* associate key to behavior */ } static abstract_func_type ** lookup (abstract_func_type *key) { /* return behavior from key */ } abstract_func_type * abstract_func_get (abstract_func_type *k) { abstract_func_type **f = lookup(k); if (f) return *f; return 0; } int abstract_func_set (abstract_func_type *k, abstract_func_type *p) { abstract_func_type **f = lookup(k); if (f) { *f = p; return 0; } return -ENOENT; } #define DEFINE_ABSTRACT_FUNC(func) \ static int static_##func (); \ static abstract_func_type *func##_ptr = static_##func; \ int func () { return func##_ptr(); } \ static int static_##func () DEFINE_ABSTRACT_FUNC(foo) { return puts("foo"); } DEFINE_ABSTRACT_FUNC(bar) { return puts("bar"); } void abstract_func_init () { insert(foo, &foo_ptr); insert(bar, &bar_ptr); } 

然后,您最初在post中显示的swap()可以像这样实现:

 void swap (abstract_func_type *a, abstract_func_type *b) { abstract_func_type *ap = abstract_func_get(a); abstract_func_type *bp = abstract_func_get(b); abstract_func_set(a, bp); abstract_func_set(b, ap); } 

这是一个调用swap()的程序:

  puts("before swap"); foo(); bar(); swap(foo, bar); puts("after swap"); foo(); bar(); 

它的输出将是:

 before swap foo bar after swap bar foo 

要自动将抽象函数添加到查找表中,您可以在构建系统中引入一个额外的步骤,该步骤调用一个脚本来DEFINE_ABSTRACT_FUNC行,并生成一个新的源文件,该文件具有调用insert()的函数insert()对于每条这样的线。

可以在此处找到完整版的模型。