Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
可以交换C函数吗?_C_Pointers_Function Pointers - Fatal编程技术网

可以交换C函数吗?

可以交换C函数吗?,c,pointers,function-pointers,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); 编辑 这里提供了更多关于意图的数据——下面提供了一些答案,这些答案可以起作用,例如使用t

看看是否有人知道是否可以交换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,将它们指向函数并切换这些函数,从而使您能够成功调用新的交换ptr

但在交换后按函数的原始名称调用函数并没有改变。本质上,我在寻找一个与objc“swizzle”等价的c

我开始认为这是不可能的,因为c完全没有反射,并且需要实际修改二进制本身(显然不可行)。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 <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;

}

有些人不亲自尝试,只是说它很荒谬。所以我给你举个例子。

我很确定你需要函数指针的指针来交换指针,不是吗?这种类型的交换函数交换值;你真的想处理地址。示例函数调用不会真正起作用,因为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);
}

尽管主题询问交换函数,但实际上您希望模拟
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 ();
before swap
foo
bar
after swap
bar
foo
此类接口的实现可能如下所示:

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()
的程序:

其产出将是:

/* 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 ();
before swap
foo
bar
after swap
bar
foo
为了自动将抽象函数添加到查找表中,您可以在构建系统中引入一个额外的步骤,该步骤调用一个脚本,该脚本将
grep
输出
DEFINE\u abstract\u FUNC
行,并生成一个新的源文件,该文件中的每个行都有一个调用
insert()
的函数


可以找到模型的完整版本。

可以。假设一个函数指针只是一个内存地址,唯一的问题是:在哪里保存这样的地址需要是可变的。比如说,
int(*foo)(
不是真正指向
foo
指向的地方。在
*b=temp
中,可能是到
printf()
fopen()
*b
是完全荒谬的。你只能在调用函数指针时取消引用它。
*b
一开始就不是一个有效的左值。@Thokchom--虽然该注释似乎主要是关键性的,而不是建设性的,关键是你是对的。该函数是针对其他数据类型的通用指针交换的改编,显然是不正确的,因此我首先要问的问题是**请参见编辑**不,不,你误解了我。我为什么要批评你?我只是在谈论那项任务。我用粗体写了“荒谬”以引起你的注意。干杯@MilesAlden关于编辑部分:能够在运行时交换函数需要运行时决定调用哪个函数。有些语言可能有语法上的甜头,但它总是归结为某种查找,查找要调用的内容(或者在调用函数的每个地方修改二进制,这甚至常常被操作系统禁止)。在C语言中,如果您想实现这一点,就需要显式地实现,函数指针是最直接的方法(但不是唯一的方法)。在C语言中,你必须自己实现反射特性,在你需要的地方。这在函数范围内有效,但不会改变实际的函数指针地址。打印之前和之后的函数指针,您将看到。就像您可以调用func1()&func2(),它们现在被交换,但是调用foo()&bar()会显示它们不受影响。函数地址是常量;在正确的条件下,如代码段实际上是可写的,或执行许多汇编级的向导,并且如果星对齐,则不会使计算机崩溃,您不需要付出更多的努力就无法在C中移动代码:D.这确实起到了您描述的作用,使交换typedef'D ptr成为可能,如果你叫他们,他们就被打翻了;然而,我对第二个例子更感兴趣。我本质上是在寻找规则c函数在objective-c中的swizzling的等价物。这里我们调用这些指针,但是如果我调用test1(1),它仍然调用test1(),而不是test2()。有什么想法吗?@MilesAlden:函数名是“地址常量”。标准C不允许您更改它们,如果您以某种方式设法更改,则允许您启动计算机。如果您想随意切换实现,就必须有表示每个实现的函数指针,并始终通过这些指针调用函数。不过,这实际上扼杀了许多形式的优化。“允许您点燃计算机…”只是对这一点大笑,谢谢。:-)是的,这就是我在这里收集的。@cHao说UB是如何允许编译器启动编译器的,这很有趣,但它太不准确了,已经过时了。事实上,这并不适合我