【问题标题】:Is the explanation for this disastrous declaration even correct?对这一灾难性声明的解释是否正确?
【发布时间】:2017-06-07 09:31:28
【问题描述】:

我刚刚开始了一份新工作,我是唯一一个从事 C 项目的团队的一员。于是我呈现了这张图:

它已经在旧工作场所装饰了我的办公桌,我只是认为解释是理所当然的。

把它放在我们办公室门框旁边的想法很受欢迎。当我被问到,如果我理解这是在做什么,以及我是否可以在今天晚些时候解释它时,我同意并准备了一点点来解释它。

但我被卡住了。忽略语义上已经错误的附加提示,我对 2 个空参数表达式列表的出现感到困惑。

这难道不是说,void (*(*f[])())()实际上是:f,标识一个未指定大小的数组,其中包含指向函数的指针,这些函数返回指向返回 void 的函数的指针?

或者我只是因为我的 C 技能有点生疏而错过了什么?

【问题讨论】:

  • 此外,在两个地方允许没有特定大小的数组:当使用 initialization 定义数组时,编译器可以推断出大小;或者最后一个struct,它变成flexible array member。除此之外,必须指定数组的大小。
  • 文字实际上是错误的。 f 是一个未指定长度的数组(只能在两个地方使用),其中包含指向函数的指针,这些函数采用未指定类型的未指定数量的参数。这些函数返回的不是void,而是一个指向采用未指定数量或未指定类型参数的函数的指针,并且这些函数返回void。所以文本错过了数组中函数指针的返回类型。
  • 好吧,你可以盯着这样的代码,让你的思维处于螺旋状,处于精神错乱的边缘......或者你可以使用 typedef,正如已经在数百万其他帖子中讨论过的那样。它归结为:1)如果你写这样的代码,你疯了,2)如果你试图阅读和理解这样的代码,你会发疯,3)使这种语法成为可能的人绝对是疯了.

标签: c function function-pointers declaration


【解决方案1】:

对于 C 语言的初学者来说,像这样的函数声明

void f();

表示参数的个数和类型是根据函数调用来定义的。

来自 C 标准(6.7.6.3 函数声明符(包括原型))

14 标识符列表仅声明参数的标识符 的功能。函数声明器中的一个空列表,它是一部分 该函数的定义指定该函数没有 参数。 函数声明器中的空列表不是一部分 该函数的定义指定没有关于 提供参数的数量或类型

所以如果函数没有参数最好写

void f( void );

虽然这并不重要,但为了清楚起见,让我们重写声明

void(*(*f[])( ))( )

喜欢

void(*(*f[])( void ))( void )

这个声明声明了一个未指定大小的数组(数组的大小取决于初始化器的数量)指向函数的指针。这些函数没有参数,并且返回指向函数的指针,而这些函数又没有参数并且返回类型为 void。

这是一个演示程序

#include <stdio.h>

void func2(void)
{
    puts("Hello C");
}

void(*(func1)( void ))( void )
{
    return func2;
}

int main( void )
{
    void(*(*f[])( void ))( void) = { func1 };

    f[0]()();
}

void(*(*f[])())()

它的输出是

Hello C

可以通过引入 typedef 来简化声明。

例如

#include <stdio.h>

void func2(void)
{
    puts("Hello C");
}

typedef void(*FP)(void);

FP func1(void)
{
    return func2;
}

int main( void )
{
    FP ( *f[] )( void ) = { func1 };

    f[0]()();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 2020-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多