有人可以逐行解释(逐个字符,哈哈)?
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;
}
例如,我想知道为什么在第1行的末尾有()。像“这就是你如何声明指向函数的指针”这样的答案会令人满意,但是当你声明一个变量时那种类型,为什么只使用“funcptr”而没有()?
第4行和第5行。为什么你在这里有?那些不是函数,它们是函数的指针,对吧?
第9行。为什么“州”没有()?仍然是指向函数的指针,就像第5行和第6行的指针一样。
第9行。没有()的“开始”是什么?
第12行。什么?! (我知道什么是类型转换。至少我认为我做...)
第17行。为什么“state1”需要进行类型转换?这是它已经被铸造的类型。或者是因为它缺少()?
这对我理解这些概念真的有帮助。
PS。这是一个微控制器,我将用于我正在设计的电子虚拟负载。认为这是了解C的更多信息的好机会。代码来自http://c-faq.com/decl/recurfuncp.html
答案 0 :(得分:5)
如问题中所述,这来自C FAQs网站。问题是:
问:如何声明一个可以返回指向同一类型函数的指针的函数?我正在为每个状态构建一个具有一个函数的状态机,每个状态都返回指向下一个状态的函数的指针。但是我无法找到一种声明函数的方法 - 我似乎需要一个函数返回一个指向函数的指针,该函数返回一个指向函数的指针,返回指向函数的指针......,无限期。
答:你不能直接这样做。一种方法是让函数返回一个通用的函数指针(参见问题4.13),并通过一些明智的强制转换来调整类型,因为指针被传递:
然后是使用SO问题中显示的代码的第一个例子。
正如FAQ的回答所说,你不能创建一个返回指向其自身类型函数的指针的函数,因此你必须强制编译器工作。
typedef int (*funcptr)();
最后有()
因为没有它们,你有typedef int (*intptr);
或typedef int *intptr;
这不是你想要的。空括号是一个不确定的 - 不是空的 - 参数列表。 是声明函数指针的方式 - 在尝试使用我的默认编译选项进行编译之前,我将代码修改为:typedef int (*funcptr)(void);
。
因此,funcptr
是指向返回int
的函数的指针,并且(至少为了讨论的目的)不带参数。
typedef funcptr (*ptrfuncptr)();
不要在没有中间类型的情况下尝试这个!这也是一个指向函数的指针,函数返回funcptr
- 我使用typedef funcptr (*ptrfuncptr)(void);
来断言'并且没有参数'。
funcptr start(), stop();
等这些行声明了一组5个函数。同样,参数列表未指定 - 因此我将其视为拥有(void)
。这些函数返回funcptr
。但是,他们自己的类型不是funcptr
。这是答案中提出的观点。
确实,被视为名称(没有括号),start
,stop
和state1
到state3
的类型是ptrfuncptr
- 指针返回funcptr
的函数。
ptrfuncptr state = start;
变量state
的类型为ptrfuncptr
,并且已初始化(无需强制转换)以指向函数start
。请注意,这不会调用该函数;它只是初始化一个变量,就像你有int i = -37;
一样,它将i
类型的变量int
初始化为值-37
。
state = (ptrfuncptr)(*state)();
时间让大棒出局了。该行包含函数调用和强制转换。
函数指针背后的原始逻辑是'类型模拟使用'概念。例如,如果您有:
int *p;
然后在表达式中,*p
的类型为int
。使用函数指针,您有:
int (*intfuncptr)();
在表达式中,(*intfuncptr)()
代表int
;它是调用intptrfunc
指向的函数的结果。在预标准C中,(*pointer_to_function)()
表示法是使用指针起作用的唯一方法。标准C允许您省略指针周围的(*
和)
。
因此,在现代表示法中,行state = (ptrfuncptr)(*state)();
也可以写成state = (ptrfuncptr)state();
。当我学习C时,这不是一个选项,所以我仍然更喜欢显式'这是通过指向函数的指针来调用函数'符号。常见问题确实提到了这一点。
因此,该行调用state
指向的函数,并捕获state
中的返回值。但是函数返回的值是funcptr
,而不是ptrfuncptr
,因此我们需要强制编译器接受我们已经知道我们为保持沉默而做了足够多的事情。所以,(ptrfuncptr)
演员就是这样做的。
return (funcptr)state1;
由于start
返回funcptr
,但state1
是指向返回funcptr
的函数的指针,因此此处的强制转换是再次强制执行编译器接受类型不匹配。在它之后没有括号,state1
只是函数的名称,而不是函数的调用,因此具有类型ptrfuncptr
- 指向返回funcptr
的函数的指针,而不仅仅是funcptr
这是start
应该返回的内容。因此,演员是必要的。
有关更多令人兴奋的函数指针,请参阅:
typedef
works for function pointers typedef
pointers? - 一般回答,不,但指向函数的指针有一个很强的例外。 ......在那里有一个问题,讨论像state = (ptrfuncptr)(******state)();
这样的琐事(使用这个Q& A中的符号),多个明星也在工作......