简体   繁体   English

函数和状态机的通用指针

[英]Generic pointer to function and state machines

I'm not able to find in the standard anything related to generic function pointers, in the C FAQ ( Question 1.22 ) they are using: 我无法在标准中找到与泛型函数指针相关的任何内容,在他们使用的C FAQ( 问题1.22 )中:

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

Playing a bit with state machines that's my approach: 玩一下我的方法的状态机:

#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;
}

My question is: it is valid to use 我的问题是:使用是有效的

typedef void (*stm)(void);

as a generic pointer to function? 作为函数的通用指针?

it seems from what I see that we can use any type of prototype before making the cast, ie 从我看到的情况看,我们可以在制作演员之前使用任何类型的原型,即

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

is also valid 也有效

are my assumptions correct? 我的假设是否正确?

Quoting from : http://c-faq.com/ptrs/generic.html 引自: 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. 因此,您可以选择任何函数类型(通常是int( )()或void( )(),即指向返回int或void的未指定参数的函数的指针作为泛型函数指针。 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). 当你需要一个可以互换地保存对象和函数指针的地方时,可移植的解决方案是使用void *和泛型函数指针(你选择的任何类型)的并集。

So , Yes It us valid to use typedef void (*stm)(void); 所以,是的,我们有效使用typedef void (*stm)(void);

OR typedef long double (*stm)(unsigned long long); OR typedef long double (*stm)(unsigned long long); as generic pointer to function. 作为函数的通用指针。

References for the highlighted text from the link: 链接中突出显示的文本的引用:

ISO Sec. ISO秒 6.1.2.5, Sec. 6.1.2.5,Sec。 6.2.2.3, Sec. 6.2.2.3,Sec。 6.3.4 Rationale Sec. 6.3.4理由二。 3.2.2.3 H&S Sec. 3.2.2.3 H&S Sec。 5.3.3 p. 5.3.3 p。 12 12

EDIT: ( Adding more details from another answer) 编辑:(从另一个答案添加更多细节)

The reference in n1570 draft for C11 is 6.3 Conversions / 6.3.2.3 Pointers § 8: N1170草案中对C11的引用是6.3转换/ 6.3.2.3指针§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. 如果转换的指针用于调用类型与引用类型不兼容的函数,则行为未定义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM