【问题标题】:C callbacks through the function pointer and without it. Why there is no difference?C 通过函数指针和没有它的回调。为什么没有区别?
【发布时间】:2015-04-22 08:08:02
【问题描述】:

我不明白为什么不同的代码会起作用,因为它们是相同的。

#include <stdio.h>

void foo() {
    printf("Hello\n");
}

void foo1(void fn()) {
    (*fn)();
    fn();
}

void foo2(void (*fn)()) {
    (*fn)();
    fn();
}

int main(void) {
    foo1(foo);
    foo2(foo);
    return 0;
}

如果它们相同,那么为什么这不起作用?

typedef void F1(), (*F2)();

int main(void) {
    F1 f1;
    F2 f2;
    // error: lvalue required as left operand of assignment
    f1 = foo1;
    f2 = foo2;
    return 0;
}

附言

我的兴趣不在typedef(第二个例子)。
我只对第一个示例有疑问。
那就是:

  • 函数声明
  • 函数调用

【问题讨论】:

  • (*fn)(), (*****fn)() 等是相同的,因为 fn 是一个函数指示符。
  • 参考见 6.3.2.1 C11 草案版本 N1570 中的左值、数组和函数指示符

标签: c pointers callback language-lawyer


【解决方案1】:

您使用的 typedef 不正确。第一个F1() 根本不是函数指针。您的第二部分确实为函数指针 (*F2)() 正确提供了 typedef,但您没有包含类型。底线,但你没有在一行中得到 2 个函数指针类型定义:

typedef void (*F1)();
typedef void (*F2)();

将为F1F2 创建一个typedef。

就函数指针的使用而言,函数指针可以带或不带括号和解引用。

(*fn)();
fn();

两者是等价的,只是调用fn指向的函数。

【讨论】:

  • 好的,我去看看。
  • 我需要参考文档作为答案。
  • 我会找到一个参考,这需要几分钟。
  • @mezoni 我查看了 C11 标准,找不到解决这种情况的直接声明。两种形式的调用没有歧义,因为很明显,它们都指的是持有函数调用的地址。二级参考解释了这里的用法Programs as Data: Function Pointers
【解决方案2】:

线条

typedef void F1();
F1 f1;

不要将f1 声明为指针。他们将f1 声明为返回void 的函数。等价的声明是

void f1();

这可以通过以下代码进行演示,该代码将在没有任何错误或警告的情况下进行编译。请注意,如果您注释掉 F1 f1; 行,那么编译器将抱怨 "implicit declaration of function f1""conflicting types for f1",因为您有没有声明的前向引用。

typedef void F1();

int main(void)
{
    F1 f1;
    f1();
    return 0;
}

void f1()
{
    printf( "hello\n" );
}

另一方面,以下代码也将在没有警告或错误的情况下编译,但在这种情况下,编译器会将f1 视为指向函数的指针。

typedef void F1();

void foo() {
    printf( "hello\n" );
}

void foo1(F1 f1) {
    f1();
}

int main(void) {
    foo1( foo );
    return 0;
}

为什么不一样?因为 §6.7.6.3 函数声明符,第 8 段为

将参数声明为“函数返回类型”应为 调整为“指向函数返回类型的指针”,如 6.3.2.1。

【讨论】:

    猜你喜欢
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-03
    • 1970-01-01
    • 2010-09-30
    • 2017-09-14
    相关资源
    最近更新 更多