首页 > 解决方案 > 指向函数和状态机的通用指针

问题描述

我无法在标准中找到与通用函数指针相关的任何内容,在他们使用的 C 常见问题解答(问题 1.22)中:

typedef int (*funcptr)();         /* generic function pointer */
typedef funcptr (*ptrfuncptr)();  /* ptr to fcn returning g.f.p. */

玩一点状态机,这是我的方法:

#include <stdio.h>

#define STM(x) (stm)x

typedef void (*stm)(void);
typedef stm (*pstm)(void *);

stm start(void *),
    state1(void *),
    state2(void *),
    state3(void *),
    stop(void *);

static int exit_state(int state)
{
    char str[2];
    int c;

    printf("Exit state %d? ", state);
    if (fgets(str, sizeof str, stdin)) {
        while (((c = fgetc(stdin)) != '\n') && (c != EOF));
        return (str[0] == 'y') || (str[0] == 'Y');
    }
    return 0;
}

static void state_machine(pstm pstart, void *data)
{
    pstm state = pstart;

    while (state != NULL) {
        state = (pstm)(*state)(data);
    }
}

stm start(void *data)
{
    puts("Starting state machine");
    *(char **)data = "Comes from start";
    return STM(state1);
}

stm state1(void *data)
{
    puts(*(char **)data);
    puts("State 1");
    if (!exit_state(1)) {
        return STM(state1);
    }
    *(char **)data = "Comes from state 1";
    return STM(state2);
}

stm state2(void *data)
{
    puts(*(char **)data);
    puts("State 2");
    if (!exit_state(2)) {
        return STM(state2);
    }
    *(char **)data = "Comes from state 2";
    return STM(state3);
}

stm state3(void *data)
{
    puts(*(char **)data);
    puts("State 3");
    if (!exit_state(3)) {
        return STM(state1);
    }
    return STM(stop);
}

stm stop(void *data)
{
    (void)data;
    puts("Stopping state machine");
    return NULL;
}

int main(void)
{
    char *data;

    state_machine(start, &data);
    return 0;
}

我的问题是:使用是有效的

typedef void (*stm)(void);

作为函数的通用指针?

从我所看到的看来,我们可以在制作演员之前使用任何类型的原型,即

typedef long double (*stm)(unsigned long long);

也是有效的

我的假设正确吗?

标签: cfunction-pointersstate-machine

解决方案


引用自:http ://c-faq.com/ptrs/generic.html

但是,可以保证所有函数指针都可以相互转换,只要在调用之前将它们转换回适当的类型即可。因此,您可以选择任何函数类型(通常是 int ( )() 或 void ( )(),即指向返回 int 或 void 的未指定参数的函数的指针)作为泛型函数指针。当您需要一个可互换的位置来保存对象和函数指针时,可移植的解决方案是使用 void * 和通用函数指针(无论您选择哪种类型)的联合。

所以,是的,我们可以使用typedef void (*stm)(void);

typedef long double (*stm)(unsigned long long);作为函数的通用指针。

链接中突出显示的文本的参考:

ISO 秒。6.1.2.5,秒。6.2.2.3,秒。6.3.4 基本原理 3.2.2.3 H&S 部分 5.3.3 页。12

编辑:(从另一个答案添加更多细节)

C11 的 n1570 草案中的参考是 6.3 Conversions / 6.3.2.3 Pointers § 8:

指向一种类型的函数的指针可以转换为指向另一种类型的函数的指针,然后再返回;结果应与原始指针比较。如果转换后的指针用于调用类型与引用类型不兼容的函数,则行为未定义。


推荐阅读