【问题标题】:C function pointer callback as struct member with "self" reference parameter [duplicate]C函数指针回调作为具有“self”引用参数的结构成员[重复]
【发布时间】:2015-05-12 08:28:36
【问题描述】:


我想创建一个任务结构,其中包含一个指向回调的函数指针以执行所述任务。该任务包含参数,因此我想将结构的“this/self”指针传递给回调执行器函数。 这会产生循环依赖,我一直在尝试各种前向声明等,但似乎无法做到正确。我是否遗漏了一些使这成为不可能的事情,或者只是我的 C 语法魔法非常薄弱。把task*改成void*好像是作弊?

在 task.h 中:

// create a function pointer type signature for executing a task
typedef int (*executor) (task* self);

// create a task type
typedef struct {
    executor exec;  // the callback to execute the task
    ... // various data for the task
} task;

【问题讨论】:

标签: c struct function-pointers typedef self-reference


【解决方案1】:

转发声明struct task,然后使用struct task声明函数指针,然后声明struct task和typedef task

struct task;
typedef int (*executor) (struct task* self);

typedef struct task {
    executor exec;  // the callback to execute the task
    ... // various data for the task
} task;

或者按照 Jens 的建议:

首先 typedef task 前向声明 struct task,然后声明函数指针(使用 typedef task)和 struct task

typedef struct task task;
typedef int (*executor) (task* self);

struct task {
    executor exec;  // the callback to execute the task
    ... // various data for the task
};

【讨论】:

  • 如果以typedef struct task task;开头就更简单了
  • 哇,非常感谢。是的,我的 C 语法很弱。
  • 我需要了解 typedef struct typename {} typename 的惯用用法,以及它对编译器的实际意义。
  • 必须等待几分钟才能接受答案...但谢谢!节省了我很多时间。
【解决方案2】:

你必须在之前添加一个不完整类型声明,告诉编译器该类型将在以后定义。您可以“滥用”所谓的结构标签有自己的命名空间,与类型名称分开的事实所以结构标签名称可以与类型名称相同:

typedef struct task task; // typedef a struct task as "task"
typedef int (*executor) (task* self); // pointer to incomplete type

typedef struct task { // re-use struct tag name here to complete the type
    executor exec;
} task; // typedef a name for the completed type

...
task t;

【讨论】:

    【解决方案3】:

    Typedef 和 forward 首先声明结构,它应该可以工作,就像这样:

    #include <stdio.h>
    
    typedef struct task task;
    typedef int (*executor) (task* self);
    
    struct task {
        executor exectr;
        int a;
    };
    
    int exec(task* self) {
        return self->a;
    }
    
    int main(int, char**) {
        task a = { .exectr = exec, .a=10};
        printf("%d\n",a.exectr(&a));
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-23
      • 2020-06-19
      相关资源
      最近更新 更多