为什么"case::LABEL:"用 g++ 编译?

Why does "case::LABEL:" compile in g++?

本文关键字:编译 g++ LABEL case 为什么      更新时间:2023-10-16

我很惊讶地得知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。你可以找到很多这样奇怪的例子,其中有几个就在这里。