【问题标题】:How typedef works for function pointerstypedef 如何作用于函数指针
【发布时间】:2012-02-20 15:55:02
【问题描述】:

我想我可能患上了可怕的“意外程序员”病,至少在 typedef 和函数指针方面是这样。所以我一直在尝试各种涉及这些的组合,以根据我得到的所有输出来分析结果。

但由于我不断尝试不同的组合,而不是分析结果,我现在只是迷失在过程中。

我希望你们能帮我弄清楚这个烂摊子。

第一个代码示例

typedef void (print)(void);
void do_something (void) { printf("Hello World\n"); }

print *pr;
pr = &do_something;
pr(); // Hello World

第二个代码示例

typedef void (print)(void);
void do_something (void) { printf("Hello World\n"); }

print *pr;
pr = do_something;
pr(); // Hello World

上面两个代码示例是如何工作的,好像'&'对函数名没有影响

第三个代码示例

typedef void (print)(void);
void do_something (void) { printf("Hello World\n"); }

print pr;
pr = do_something; // compile error
pr = &do_something; // compile error
pr();

我希望上述任务之一在这里工作,但该死!我真的不明白函数指针(也可能是 typedef)。

【问题讨论】:

  • 嗯...我认为您应该让自己成为“专家 C 编程”,它解释了 C 的 var 定义规则。我会尽量在网上帮你找
  • 只是google Expert C编程,第一本就是书。搜索“声明是如何形成的”,我想你会得到答案

标签: c++ c syntax function-pointers typedef


【解决方案1】:

函数名的地址和普通函数名的含义相同,所以&对函数名没有影响。

同样,当使用函数指针时,多重解引用也不成问题:

#include <stdio.h>
typedef void print(void);
static void dosomething(void) { printf("Hello World\n"); }

int main(void)
{
    print *f1 = dosomething;
    print *f2 = &dosomething;
    f2();
    (f1)();
    (*f1)();
    (**f2)();
    (***f1)();
    (****f2)();
    (*****f1)();
}

编译干净:

gcc -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition -std=c99 xx.c -o xx

我不会说多星是好的风格;不是。这是“奇怪的,而且(是的,你可以这么说)反常的”。一颗就足够了(一颗星主要适用于像我这样在标准说“可以通过指针调用函数而不使用(*pointer_to_function)(arg1, arg2) 符号;你可以只写pointer_to_function(arg1, arg2)如果你喜欢”)。是的,这很奇怪。不,没有其他类型(或类型的类别)表现出相同的行为,谢天谢地。

【讨论】:

  • 现在这很奇怪,我可以说是反常的。尝试并实际编译。 :)
  • +1,为了清楚起见,函数和函数指针并不相同,但在大多数情况下(尽管不是全部),前者往往会自动衰减为后者。在表达式**f2 中,函数指针被取消引用,结果函数立即衰减回一个指针,然后再次被取消引用。
  • 数组具有类似但不相同的“自动衰减”行为。对于int x[10];x&amp;x的地址相同。但是它们的类型不同,你不能使用这里显示的漂亮的星空塔。
【解决方案2】:

关于函数指针的问题在于它们是函数指针! :-) 这就是你如何让你的第三个示例工作的方式:

#include <stdio.h>
typedef void (*print)(void);
//            ^
void do_something (void) { printf("Hello World\n"); }
int main (void) {
    print pr;
    pr = do_something; // &do_something would also work.
    pr();
    return 0;
}

就您使用funcName 还是&amp;funcName 而言,这并不重要(至少在C 中)。 6.3.2.1 Lvalues, arrays and function designators 部分指出:

函数指示符是具有函数类型的表达式。除非它是 sizeof 运算符或一元 & 运算符的操作数,否则“函数返回类型”类型的函数指示符将转换为“指向函数返回类型的指针”类型的表达式。

【讨论】:

    【解决方案3】:

    事实证明,在 C/C++ 中,funcname&amp;funcname 都会产生 funcname 的地址,并且可以分配给函数指针变量。这实际上只是为语言设计语法的一个奇怪之处。

    【讨论】:

      【解决方案4】:

      与 C 一样,C++ 具有指向函数的指针:例如,void (*)() 是指向不带参数且不返回值的函数的指针。但是,C++ 也引入了对函数 void (&amp;)() 的引用,并且两者之间存在隐式转换(虽然我不记得确切的规则)。

      因此:

      • funcname 是对函数的引用
      • &amp;funcname 是函数指针

      请注意,获取重载函数的地址(或引用)需要将 static_cast 精确到类型(以解决重载问题)。

      【讨论】:

        猜你喜欢
        • 2022-10-07
        • 2011-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-09
        相关资源
        最近更新 更多