comp.lang.c faq: Function that can return a pointer to a function of the same type

别来无恙 提交于 2019-12-14 02:16:46

问题


The following is Question 1.22 from the comp.lang.c faq.

Why is the definition of ptrfuncptr necessary?

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:


ptrfuncptr is intended to serve as a specific pointer type for pointers to various "state" functions, exactly as it is used in the original code. Trying to replace it with funcptr would make no sense. The purpose of funcptr is to serve as a "generic" pointer. It always has to be cast to proper "specific" function pointer type before use, which is ptrfuncptr in this example.

In your version of the code this

funcptr state = start;

declares state as a pointer to function returning an int, while in reality start returns a function pointer. Formally, this initialization is a constraint violation (aka "will not even compile") because the types are not compatible.

Later you do

state = (*state)();

which is an attempt to assign an int value returned by (*state)() to pointer variable state, which makes no sense whatsoever and, formally, is also a constraint violation.

And so on and so forth.

If your code compiles, its behavior is still undefined. But again, formally, this should not even compile due to multiple constraint violations. I'm sure your compiler issued quite a few diagnostic messages for your version of the code.

The only reason it can "work" is just a lucky coincidence of how that undefined behavior played out in practice. It preserved pointer information during these conversions (like a 32-bit platform with 32-bit int and 32-bit pointers). On a 64-bit platform it has a much smaller chance to "work".




回答2:


The key to understanding the code is 4.13 from the C faq:

It is guaranteed, however, that all function pointers can be interconverted, as long as they are converted back to an appropriate type before calling

We have a function that returns a pointer to a function of the same type. But since we can't define that directly in C we employ a trick. We just make the function return a generic function pointer and then cast it to the appropriate type. We are allowed to do that because of 4.13 above.

Why is funcptr a generic pointer? Isn't it a pointer to a function that returns int? Why is that generic?

According to 4.13 all function pointers can be interconverted so it doesn't really matter how we define it. Just make sure to cast it to the right type before calling it.

Why is the definition of ptrfuncptr necessary?

Because that is the type of the state functions, they are functions that return a function pointer.

Shouldn't the code return (funcptr)state1; in the function start() be return (ptrfuncptr)state1;? Because state1 is a pointer to a fuction returning funcptr?

What start() actually returns is a ptrfuncptr but we defined it as a fuction returning funcptr therefore we just cast the result to funcptr. We cast it to the correct type in the statemachine: state = (ptrfuncptr)(*state)();

Why not define all the state functions with the right type to begin with instead of doing all the pointer casting?

Because this would be a recursive definition.



来源:https://stackoverflow.com/questions/39472619/comp-lang-c-faq-function-that-can-return-a-pointer-to-a-function-of-the-same-ty

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!