以下是comp.lang.c faq。
中的Question 1.22为什么ptrfuncptr
的定义必要?
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;
}
答案 0 :(得分:1)
ptrfuncptr
旨在作为指向各种"状态"的指针的特定指针类型。功能,与原始代码中使用的功能完全相同。试图用funcptr
替换它是没有意义的。 funcptr
的目的是作为"泛型"指针。它总是必须被投射到适当的"特定的"使用前的函数指针类型,在本例中为ptrfuncptr
。
在您的代码版本中
funcptr state = start;
将state
声明为返回int
的函数的指针,而实际上start
返回一个函数指针。形式上,这种初始化是一种约束违规(又称"甚至不会编译")因为类型不兼容。
稍后你做
state = (*state)();
尝试将int
返回的(*state)()
值分配给指针变量state
,这没有任何意义,并且正式地也是违反约束。
依此类推。
如果您的代码编译,其行为仍未定义。但是,正式地说,由于多个约束违规,这甚至不应该编译。我确定您的编译器为您的代码版本发出了很多诊断消息。
它能够"工作的唯一原因"只是这个未定义的行为在实践中如何发挥的幸运巧合。它在这些转换期间保留了指针信息(例如具有32位int
和32位指针的32位平台)。在64位平台上,工作"工作的机会要小得多。
答案 1 :(得分:1)
理解代码的关键是来自C faq的4.13:
但是,保证所有函数指针都可以互相转换,只要它们在调用之前转换回适当的类型
我们有一个函数返回指向同一类型函数的指针。但由于我们无法直接在C中定义,我们采用了一种技巧。我们只是让函数返回一个泛型函数指针,然后将其强制转换为适当的类型。由于上述4.13,我们被允许这样做。
为什么funcptr是通用指针?它不是指向返回int的函数的指针吗?为什么这是通用的?
根据4.13,所有函数指针都可以互相转换,因此我们定义它的方式并不重要。只需确保在调用之前将其转换为正确的类型。
为什么必须定义ptrfuncptr?
因为这是state
函数的类型,它们是返回函数指针的函数。
函数return (funcptr)state1;
中的代码start()
不应该是return (ptrfuncptr)state1;
吗?因为state1是指向返回funcptr的函数的指针?
start()实际返回的是ptrfuncptr
,但我们将其定义为返回funcptr
的函数,因此我们只将结果转换为funcptr
。我们将其转换为statemachine
:state = (ptrfuncptr)(*state)();
为什么不首先使用正确的类型定义所有state
函数而不是执行所有指针转换?
因为这将是一个递归定义。