c - 函数和状态机的通用指针

标签 c function-pointers state-machine

我无法在标准中找到与通用函数指针相关的任何内容,在他们使用的 C FAQ (Question 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);

作为指向函数的通用指针?

据我所知,我们可以在制作类型转换之前使用任何类型的原型(prototype),即

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

也是有效的

我的假设是否正确?

最佳答案

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

It is guaranteed, however, that all function pointers can be interconverted, as long as they are converted back to an appropriate type before calling. Therefore, you can pick any function type (usually int ()() or void ()(), that is, pointer to function of unspecified arguments returning int or void) as a generic function pointer. When you need a place to hold object and function pointers interchangeably, the portable solution is to use a union of a void * and a generic function pointer (of whichever type you choose).

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

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

链接中突出显示的文本的引用:

国际标准化组织6.1.2.5,第二节6.2.2.3,第二节6.3.4 理由秒。 3.2.2.3 健康与安全部5.3.3 页12

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

C11 的 n1570 草案中的引用是 6.3 Conversions/6.3.2.3 Pointers § 8:

A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.

关于c - 函数和状态机的通用指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56241467/

相关文章:

使用函数指针在测试程序中编译错误

events - 状态机将事件推送到自己的事件队列

azure - 使用 Azure 队列作为状态机

c - 如何在状态机上使用全局变量

c - 用 C 语言编写一个程序,接受自然数 n 和基数 b,并输出 b 中 n 的数字

c - 是否有描述 C 函数名称 "stand for"的文档(不是它们的作用——而是缩写名称的含义)?

c - 为依赖文件生成单独的 .o

c - 数组等于另一个数组

c - 在 GCC 中实现编译时只读函数指针表

c - 结构和函数的段错误