想知道是否有人知道是否可以交换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。
我开始认为这是不可能的,因为c完全缺乏反射,并且需要实际修改二进制本身(显然不可行)。 d:
欢迎评论。
答案 0 :(得分:9)
如果使用如下所示的函数指针,则为是
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 <stdio.h>
#include <stdlib.h>
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
有些人不会自己尝试,只是说它荒谬。所以我举个例子。
答案 1 :(得分:3)
我很确定你需要指向交换指针的函数指针,不是吗?这种类型的交换功能交换值;你真的想要处理地址。示例函数调用不会真正起作用,因为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);
答案 2 :(得分:1)
您的代码在分配时会给出“无效左值”之类的错误。正如我在您的代码中看到的那样,您正在尝试交换指针而不更改其值,因此请查看下面的解决方案。
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);
}
答案 3 :(得分:1)
是的,你可以。认为一个函数指针只是一个内存地址,单个requeriment是:你将保持这样的地址需要是可变的。比方说,int (*foo)()
并不是foo
指向的地方。可以是printf()
或fopen()
。
答案 4 :(得分:0)
虽然主题询问有关交换功能的问题,但您实际上想要模仿swizzle
所做的事情。这只是意味着您希望能够调用相同的函数名称,但让它做一些不同的事情。
仅指针解决方案不会为您提供该行为。如果这对您来说并不重要,那么您应该采用其中一个仅提供解决方案的函数指针。如果它对 非常重要,那么,您需要引入一个抽象层。抽象可以使用引擎盖下的函数指针(尽管还有其他解决方案)。
此界面的用户的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);
}
然后,您最初在帖子中显示的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
要自动将抽象函数添加到查找表中,您可以在构建系统中引入一个额外步骤,该步骤调用一个脚本,grep
DEFINE_ABSTRACT_FUNC
行insert()
行,并生成新源具有针对每个此类行调用{{1}}的函数的文件。
可以找到完整版的模型here。