为什么我能够将函数引用分配给匿名函数指针变量?

20
以下代码可以顺利编译,但我不确定原因。可以有人解释一下为什么这是合法的吗?
我正在使用g++ (Debian 6.1.1-10) 6.1.1 20160724进行编译。
#include <iostream>

int sum(int x, int y) { return x + y; }

int main(int argc, char *argv[])
{
    using std::cout;

    int (*) (int, int) = &sum;
    cout << "what" << '\n';
}

补充说明

以下程序在使用g++版本5.4.0编译时可以正常通过,但在gcc中无法编译。

int main()
{
    int (*) = 20;
}

那是一个无关紧要的细节。它是一个指针。它被分配给一个匿名函数指针。但是"int = 7;"不能编译。"int *=nullptr;"也不能。这里可能有一个最烦人的解析的表兄弟。 - Sam Varshavchik
1
这也编译了void foo();... int (*) (int, int) = &foo; - 有些奇怪的事情正在发生。(g++ 5.1.0) - Richard Critten
1
算了吧。int (*)(int, int); 也可以编译。 - Sam Varshavchik
1
请将编译器信息添加到问题中。 - R Sahu
3
同时,“int (*) (int, int) = 5.3;”(试图避免右侧的指针衰退) - Richard Critten
显示剩余5条评论
1个回答

11

很可能与Zack Weinberg报告的这个错误相关:

Bug 68265 - 在 'int (*){}' 后直到下一个闭合大括号之前会默默接受任意语法无意义的内容

(来自为什么这段看起来不正确的代码可以在g++ 6.0上成功编译? :)

C++编译器未能诊断出形如以下代码的语法错误:

  int main()
  {
      int (*) {}
         any amount of syntactic nonsense
         on multiple lines, with *punctuation* and ++operators++ even...
         will be silently discarded
         until the next close brace
  }

使用 -pedantic -std=c++98 会得到 "warning: extended initializer lists only available with -std=c++11 or -std=gnu++11" 警告,但是使用 -std=c++11 就不会有任何提示。

如果移除 'int ( * ) { }' 的任何一个或多个标记,就会得到一个错误。此外,C编译器没有这个bug.

当然,如果您尝试其他变量如int (*) (int, int) {}等,它会被错误地编译通过。有趣的是,与之前的重复/错误报告的不同之处在于,int (*) (int, int) = asdf需要asdf成为作用域内的名称才能编译通过。但我非常怀疑这些错误的本质不同,因为核心问题是GCC允许省略declarator-id

[n4567 §7/8]: "init-declarator-list中的每个init-declarator恰好包含一个declarator-id,该declarator-id是由该init-declarator声明的名称,因此是声明中声明的名称之一。"

以下是一个奇怪的例子:

int (*) (int, int) = main;
在这种特定情况下,GCC不会对获取main函数地址的操作报错(就像数组一样,&main等同于main)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接