问题描述
以下代码使用g++ 4.8.1编译成功:
The following code compiles successfully with g++ 4.8.1:
int main()
{
int(*)();
}
它看起来像一个简单的函数指针声明:
It looks like a simple declaration of a pointer to function:
int(*f)();
它不能用 clang 3.4 和 vc++ 2013 编译.
It doesn't compile with clang 3.4 and vc++ 2013.
它是编译器错误还是标准的黑暗地方之一?
Is it a compiler bug or one of dark places of the standard?
int(*)();
int(*);
int(*){};
int(*());
带有这些奇怪代码片段的实时示例.
更新 1: @Ali 添加了一些有趣的信息在评论中:
Update 1: @Ali added some interesting information in the comments:
所有 4 种情况在使用 clang 3.5 主干 (202594) 时都会出现编译错误,而使用 gcc 4.9 主干 (20140302) 时编译良好.行为与 -std=c++98 -pedantic
相同,除了 int(*){};
是可以理解的;扩展初始值设定项列表仅适用于 -std=c++11
.
All 4 cases give a compile error with clang 3.5 trunk (202594) and compile fine with gcc 4.9 trunk (20140302). The behavior is the same with
-std=c++98 -pedantic
, except forint(*){};
which is understandable; extended initializer lists only available with-std=c++11
.
更新 2: 正如 @CantChooseUsernames 在 他的答案即使初始化并且没有组装,它们仍然可以正常编译即使没有启用任何优化,g++ 也会为它们生成(无论是否初始化):
Update 2: As @CantChooseUsernames noted in his answer they still compile fine even with initialization and no assembly is generated for them by g++ (neither with nor without initialization) even without any enabled optimization:
int(*)() = 0;
int(*) = 0;
int(*){} = 0;
int(*()) = 0;
带初始化的实时示例.
更新 3: 我很惊讶地发现 int(*)() = "Hello, world!";
也可以正常编译(而 int(*p)() = "Hello, world!";
当然不会编译).
Update 3: I was really surprised to find that int(*)() = "Hello, world!";
compiles fine, too (while int(*p)() = "Hello, world!";
doesn't compile, of course).
更新 4: 非常棒,但 int(*){} = Hello, world!;
编译良好.还有下面这段极其奇怪的代码:int(*){}() = -+*/%&|^~.,:!?$()[]{};
(现场示例).
Update 4: It is fantastic but int(*){} = Hello, world!;
compiles fine. And the following extremely strange piece of code, too: int(*){}() = -+*/%&|^~.,:!?$()[]{};
(live example).
更新 5: 正如 @zwol 在 他的评论
这个和一些相关的句法问题正在被跟踪为 gcc bug 68265.
This and a number of related syntactic problems are being tracked as gcc bug 68265.
推荐答案
根据 C++ 标准(第 7 节声明第 6 页)
According to the C++ Standard (p. #6 of section 7 Declarations)
6 init-declarator-list 中的每个 init-declarator 完全包含一个 declarator-id,即由它声明的名称init-declarator,因此是声明所声明的名称之一
6 Each init-declarator in the init-declarator-list contains exactly one declarator-id, which is the name declared by that init-declarator and hence one of the names declared by the declaration
所以这只是一个编译器错误.
So it is simply a compiler bug.
虽然我无法用我的 MS VC++ 2010 编译它,但有效代码可能看起来像示例(除了您显示的函数指针声明).
The valid code could look as for example (apart from the function pointer declaration showed by you) though I can not compile it with my MS VC++ 2010.
int(*p){};
您用于测试的编译器似乎允许不带 declarator-id 的声明.
It seems that the compiler you are using for testing allows declarations without a declarator-id.
还要考虑第 8.1 节类型名称的以下段落
Also take into account the following paragraph of section 8.1 Type names
1 显式指定类型转换,并作为参数sizeof、alignof、new 或 typeid,类型的名称应为指定的.这可以通过 type-id 来完成,它在语法上是该类型的变量或函数的声明省略了实体名称.
1 To specify type conversions explicitly, and as an argument of sizeof, alignof, new, or typeid, the name of a type shall be specified. This can be done with a type-id, which is syntactically a declaration for a variable or function of that type that omits the name of the entity.
这篇关于用 g++ 编译的奇怪代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!