为什么"case::LABEL:"用 g++ 编译?
Why does "case::LABEL:" compile in g++?
我很惊讶地得知g++(4.9)正在编译这个(而gcc不会):
#include <stdio.h>
enum
{
ONE = 1,
TWO = 2,
THREE = 3
};
int main(int argc, char* argv[])
{
int sw = 2;
switch (sw)
{
case::ONE:
{
printf("1n");
break;
}
case::TWO:
{
printf("2n");
break;
}
case::THREE:
{
printf("3n");
break;
}
default:
{
printf("defaultn");
}
}
}
g++预处理器如何将"case"与"::ONE:"分离?
g++预处理器如何将"case"与"::ONE:"分离?
将::
解释为引用全局命名空间的不是预处理器,而只是编译器。
案例标签将被解析为
case :: THREE :
这完全可以,因为enum
值出现在全局名称空间(::
)中。
它不是预处理器。C编译器(其标记化器)认为:
case :: ONE
这在c++中是可以的。::运算符表示根命名空间。C没有这样的东西。
您有一个简单的枚举,而不是作用域的枚举(请参阅:enum class
)。普通枚举在根作用域中,因此可以编写::ONE
。
使用作用域枚举,您可以执行以下操作:
enum class Scoped { FIRST, LAST = 9};
//...
case Scoped::FIRST : //...
g++中的标记化器(因为这是C++的一个特性)可以解析,即使您没有在case
关键字和枚举器之间留下空白。
在编译过程的词法分析阶段,程序文件中的字符流被转换为令牌。这里使用的一种流行算法是最大咀嚼算法,其中最长匹配的合法令牌被视为预期令牌。在本例中,它将case::ONE:
分解为case
、::
、ONE
和:
。
还有一些缺点:x = y/*z
是一个错误,因为/*
是最长的匹配合法令牌,而用户可能想说x = y / *z
。你可以找到很多这样奇怪的例子,其中有几个就在这里。