函数和状态机的通用指针
Generic pointer to function and state machines
我无法在标准中找到任何与通用函数指针相关的内容,在他们使用的 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);
作为指向函数的通用指针?
据我所知,我们可以在制作演员表之前使用任何类型的原型,即
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);
作为指向函数的通用指针。
对 link 中突出显示的文本的引用:
ISO 秒。 6.1.2.5,第二节6.2.2.3,第二节6.3.4
理由秒。 3.2.2.3
健康与安全部5.3.3 页12
编辑:(从另一个答案添加更多细节)
C11 的 n1570 草案中的参考是 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.
我无法在标准中找到任何与通用函数指针相关的内容,在他们使用的 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);
作为指向函数的通用指针?
据我所知,我们可以在制作演员表之前使用任何类型的原型,即
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);
作为指向函数的通用指针。
对 link 中突出显示的文本的引用:
ISO 秒。 6.1.2.5,第二节6.2.2.3,第二节6.3.4 理由秒。 3.2.2.3 健康与安全部5.3.3 页12
编辑:(从另一个答案添加更多细节)
C11 的 n1570 草案中的参考是 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.