用 g++ 编译的奇怪代码

2022-01-23 00:00:00 gcc g++ c++ c++11

以下代码使用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?

  1. 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 for int(*){}; 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:

  1. 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.

相关文章