【问题标题】:comp.lang.c faq: Function that can return a pointer to a function of the same typecomp.lang.c faq: 可以返回指向同类型函数的指针的函数
【发布时间】:2016-09-13 14:33:31
【问题描述】:

以下是 comp.lang.c 常见问题解答中的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;
}

【问题讨论】:

  • 返回int 的函数与返回其他内容的函数(在本例中为指向函数的指针)不同。我看不到funcptr state = start; 在第二个 sn-p 中是如何编译的(它至少应该是一个警告)。
  • 来自同一个常见问题页面的第二种方法更好(正确且更清晰)。
  • @Roland 这只是一个围绕 C 类型系统的游戏。代码本质上试图做通常用汇编语言做的事情。汇编语言通常(如果有的话)不强制也不验证原始数字类型以外的类型。

标签: c pointers function-pointers


【解决方案1】:

ptrfuncptr 旨在用作指向各种“状态”函数的指针的特定指针类型,与原始代码中使用的完全一样。试图用funcptr 替换它是没有意义的。 funcptr 的目的是充当“通用”指针。在使用之前,它始终必须转换为正确的“特定”函数指针类型,在本例中为 ptrfuncptr

在你的代码版本中

funcptr state = start;

state 声明为指向返回int 的函数的指针,而实际上start 返回一个函数指针。形式上,这种初始化是违反约束的(又名“甚至不会编译”),因为类型不兼容。

稍后再做

state = (*state)();

这是试图将(*state)() 返回的int 值分配给指针变量state,这毫无意义,而且形式上也是违反约束的。

等等等等。

如果您的代码编译,它的行为仍然是未定义的。但是,再一次,正式地,由于多次违反约束,这甚至不应该编译。我确信您的编译器针对您的代码版本发出了相当多的诊断消息。

它可以“工作”的唯一原因只是这种未定义行为在实践中如何发挥作用的幸运巧合。它在这些转换过程中保留了指针信息(例如具有 32 位 int 和 32 位指针的 32 位平台)。在 64 位平台上,它“工作”的机会要小得多。

【讨论】:

  • @Roland:Any 函数指针类型可以用作“通用”函数指针类型(从某种意义上说,它在转换中保留了指针信息)。上述代码的作者选择了int (*)()。他们本可以选择double (*)(char)(破坏你的版本,顺便说一句)或其他任何东西。但他们选择了int (*)()。他们可能只是觉得int 返回类型在 C 中看起来更“通用”。
  • @Roland:他们将所有内容都转换为funcptr,因为他们做出了设计决定——所有“状态”指针都作为通用指针传递。因此,所有接口都以funcptr 的形式实现,并尽可能将所有内容转换为funcptr
【解决方案2】:

理解代码的关键是C faq中的4.13

但是,保证所有函数指针都可以相互转换,只要在调用之前将它们转换回适当的类型

我们有一个函数,它返回一个指向同类型函数的指针。但是由于我们不能直接在 C 中定义它,所以我们使用了一个技巧。我们只是让函数返回一个通用函数指针,然后将其转换为适当的类型。由于上面的 4.13,我们被允许这样做。

为什么 funcptr 是通用指针?它不是指向返回 int 的函数的指针吗?为什么是通用的?

根据 4.13,所有函数指针都可以相互转换,因此我们如何定义它并不重要。只需确保在调用之前将其转换为正确的类型即可。

为什么需要定义ptrfuncptr?

因为这是 state 函数的类型,所以它们是返回函数指针的函数。

函数start()中的代码return (funcptr)state1;不应该是return (ptrfuncptr)state1;吗?因为 state1 是一个指向返回 funcptr 的函数的指针?

start() 实际返回的是ptrfuncptr,但我们将其定义为返回funcptr 的函数,因此我们只需将结果转换为funcptr。我们将其转换为statemachine 中的正确类型:state = (ptrfuncptr)(*state)();

为什么不使用正确的类型开始定义所有 state 函数,而不是执行所有指针转换?

因为这将是一个递归定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-06
    • 1970-01-01
    相关资源
    最近更新 更多