是否可以交换C函数?

时间:2013-05-16 05:36:56

标签: c pointers function-pointers

想知道是否有人知道是否可以交换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:

欢迎评论。

5 个答案:

答案 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_FUNCinsert()行,并生成新源具有针对每个此类行调用{{1}}的函数的文件。

可以找到完整版的模型here