C函数指针:从函数返回函数指针[duplicate]

oknwwptz  于 2022-12-22  发布在  其他
关注(0)|答案(2)|浏览(196)
    • 此问题在此处已有答案**:

(9个答案)
昨天关门了。
我目前正在学习C语言,为了让代码更易读、更容易写,我发现自己需要在函数中创建一个函数(闭包),然后返回这个函数。下面是我正在尝试做的事情:

#typedef int (int_predicate*)(int);
int_predicate equals(int x) {
  int ret(int y) { return x == y; }
  return ret;
}

现在,这个,* 不工作,我明白 *:我在一个函数内部创建了这个闭包(ret),所以一旦这个函数返回,指针就不再相关了,因为它是在堆栈上定义的,这类似于我为一个更简单的类型的指针做的事情:

int* bad_int_ptr_function() {
  int intOnTheStack;
  int* ptr = &intOnTheStack;
  return ptr;
}

那么,我怎样才能达到我想要的--在一个函数中创建一个闭包并返回它?如果所指向的类型的大小是已知的,我就能够使用malloc,如果我愿意,我可以在它后面使用memcpy。但是,我只能 * 假设**一个函数的大小不能用sizeof找到。* * 因为函数可以有任意数量的行。
这是C,我不能使用C特有的语法或库(我最近听说C有lambda表达式--如果我能使用C++就好了,但我不能,这是C特有的课程)。

vsdwdz23

vsdwdz231#

在C语言中没有(简单、健壮的)方法来创建闭包。
但有一种方法可以让你更接近:可以返回一个struct,其中包含一个函数指针,该指针可以将struct或其地址作为参数:

typedef int ( *intClosureFuncPtr )( struct intClosure * );

struct intClosure
{
    int tag // can be used to differentiate multiple struct
            // types in a union
    intClosureFuncPtr func;
        .
        .
    // fields as necessary
};

关闭功能:

int closureFunc0( struct intClosure *c )
{
       .
       .
       .
    return( 0 );
}

int closureFunc42( struct intClosure *c )
{
       .
       .
       .
    return( 42 );
}

调用创建闭包并返回struct的函数:

struct intClosure someFunc( ... )
{

    struct intClosureInstance = { 0 };

    intClosure.tag = 7;
    intClosure.func = closureFunc42;
    // fill in rest of the struct fields as needed 

    return( intClosureInstance );
}

用法:

struct intClosure closureInstance = someFunc(...);
    .
    .
    .

// call the closure:
int result = closureInstance.func( &closureInstance );

也可以malloc()struct并通过地址返回它,但这需要调用者free()它。您需要评估您的"闭包" struct的大小,并且必须通过值传递它,以避免要求调用者free()它的额外复杂性。
注意这个"闭包"的返回类型是固定的,在POSIX和Windows系统上有可能允许动态选择返回类型,因为这两个系统都有一个由所有变量和函数共享的平面地址空间(当前的Windows是这样的),但是这些黑客可能会陷入C标准没有定义的行为。

    • 如果您希望限制C "闭包"只能从创建它们的线程中调用,在任何时刻每个线程只能有一个未完成的"闭包",那么您可以使用线程特定的数据将信息传递给闭包生成时由函数指针返回的实际函数,然后可以直接调用该函数,而不需要通过上面的struct方法进行任何间接调用。
u0sqgete

u0sqgete2#

在标准C中,不能将闭包定义为函数,但可以使用数据结构模拟它们:

#include <stdio.h>

typedef struct int_predicate_t {
    int (*func)(struct int_predicate_t *s, int x);
    int y, z;
} int_predicate_t;

#define APPLY(p, x)  ((p).func(&(p), x))

int equal_func(struct int_predicate_t *s, int x) {
    return x == s->y;
}

int greater_func(struct int_predicate_t *s, int x) {
    return x > s->y;
}

int between_func(struct int_predicate_t *s, int x) {
    return x >= s->y && x <= s->z;
}

int_predicate_t equals(int y) {
    int_predicate_t s = { equal_func, y, 0 };
    return s;
}

int_predicate_t greater(int y) {
    int_predicate_t s = { greater_func, y, 0 };
    return s;
}

int_predicate_t between(int y, int z) {
    int_predicate_t s = { between_func, y, z };
    return s;
}

int main() {
    int_predicate_t p1 = equals(42);
    int_predicate_t p2 = greater(10);
    int_predicate_t p3 = between(1, 100);

    printf("p1(42) = %d\n", APPLY(p1, 42));
    printf("p2(42) = %d\n", APPLY(p2, 42));
    printf("p3(42) = %d\n", APPLY(p3, 42));
    printf("p1(0) = %d\n", APPLY(p1, 0));
    printf("p2(0) = %d\n", APPLY(p2, 0));
    printf("p3(0) = %d\n", APPLY(p3, 0));

    return 0;
}

相关问题