涉及函数指针和状态机的代码说明

Dra*_*uri 3 c function-pointers state-machine

有人可以逐行解释这一点(可能是逐个字符,哈哈)?

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

funcptr start(), stop();
funcptr state1(), state2(), state3();

void statemachine()
{
    ptrfuncptr state = start;

    while(state != stop)
        state = (ptrfuncptr)(*state)();
}

funcptr start()
{
    return (funcptr)state1;
}  
Run Code Online (Sandbox Code Playgroud)

例如,我想知道为什么在第1行的末尾有()."只是你如何声明指向函数的指针"这样的答案会令人满意,但是当你声明一个这种类型的变量时,为什么只使用"funcptr"而没有()?

第4行和第5行.为什么你在这里有?那些不是函数,它们是函数的指针,对吧?

第9行.为什么"状态"没有()?仍然是指向函数的指针,就像第5行和第6行的指针一样.

第9行.没有()的"开始"是什么?

第12行.什么?!(我知道什么是类型转换.至少我认为我做...)

第17行.为什么"state1"需要进行类型转换?这是它已经被铸造的类型.或者是因为它缺少()?

这对我理解这些概念真的很有帮助.

PS.这是一个微控制器,我将用于我正在设计的电子虚拟负载.认为这是一个了解更多关于C的好机会.代码来自http://c-faq.com/decl/recurfuncp.html

Jon*_*ler 5

如问题中所述,这来自C FAQs网站.问题是:

问:如何声明一个可以返回指向同一类型函数的指针的函数?我正在构建一个状态机,每个状态都有一个函数,每个函数都返回一个指向下一个状态函数的指针.但是我找不到声明函数的方法 - 我似乎需要一个函数返回一个指向函数的指针,该函数返回一个指向函数的指针,返回指向函数的指针......,无限制.

答:你不能直接做到这一点.一种方法是让函数返回一个通用函数指针(参见问题4.13),并通过一些明智的强制转换来调整类型,因为指针被传递:

然后是使用SO问题中显示的代码的第一个例子.

正如FAQ的回答所说,你不能创建一个返回指向它自己的函数类型的函数的函数,所以你必须强迫编译器工作.

第1行: typedef int (*funcptr)();

这有()最后因为没有他们,你有typedef int (*intptr);或typedef int *intptr;不是你想要的.空括号是一个不确定的 - 不是空的 - 参数列表.这是你声明一个函数指针的方式 - 在尝试使用我的默认编译选项进行编译之前,我将代码修改为:typedef int (*funcptr)(void);.

funcptr因此,A 是指向返回an的函数的指针,int并且(至少为了讨论的目的)不带参数.

第2行: typedef funcptr (*ptrfuncptr)();

没有中间类型,请不要尝试这个!这也是一个指向函数的指针,函数返回一个funcptr- 我常常typedef funcptr (*ptrfuncptr)(void);断言'并且不带参数'.

第4和第5行:funcptr start(), stop();等

这些行声明了一组5个函数.同样,参数列表未指定 - 因此我将把它们视为具有(void).这些函数返回一个funcptr.但是,他们自己的类型不是funcptr.这是答案中提出的观点.

事实上,视为一个名称(没有括号),类型start,stop和state1通过state3是ptrfuncptr-指针返回的功能funcptr.

第9行: ptrfuncptr state = start;

变量state属于类型ptrfuncptr,并且初始化(无需转换)指向函数start.请注意,这不会调用该函数; 它只是初始化一个变量,就像你拥有int i = -37;它一样,它将一个i类型的变量初始化int为该值-37.

第12行: state = (ptrfuncptr)(*state)();

是时候把大棒拿出去了.该行包含函数调用和强制转换.

函数指针背后的原始逻辑是'类型模仿使用'概念.例如,如果您有:

int *p;
Run Code Online (Sandbox Code Playgroud)

然后在表达式中,*p有类型int.使用函数指针,您可以:

int (*intfuncptr)();
Run Code Online (Sandbox Code Playgroud)

在表达中,(*intfuncptr)()代表一个int; 它是调用指向的函数的结果intptrfunc.在预标准C中,(*pointer_to_function)()符号是使用指针函数的唯一方法.标准C允许您省略指针(*和)周围.

因此,在现代符号中,state = (ptrfuncptr)(*state)();也可以写出该行state = (ptrfuncptr)state();.当我学习C时,这不是一个选项,所以我仍然更喜欢显式的'这是通过指向函数的指针来调用函数'.FAQ确实提到了这一点.

因此,该行调用指向的函数state,并捕获返回值state.但是函数返回的值是a funcptr,而不是a ptrfuncptr,所以我们需要强迫编译器接受我们已经知道我们正在做什么来保持沉默.所以,(ptrfuncptr)演员就是这么做的.

第17行: return (funcptr)state1;

由于start返回a funcptr,但是state1是指向返回a的函数的指针funcptr,此处的强制转换再一次是强制编译器接受类型不匹配所必需的.如果没有后括号,state1是函数的只是名字,而不是函数的调用,因此具有类型ptrfuncptr-指针函数返回funcptr,而不仅仅是funcptr这正是start应该返回.所以,演员阵容是必要的.

有关更多令人兴奋的函数指针,请参阅:

...在某个地方有一个问题,讨论琐事state = (ptrfuncptr)(******state)();(使用来自这个Q&A的符号),多个明星也工作......