【问题标题】:Why does "case::LABEL:" compile in g++? [duplicate]为什么“case::LABEL:”在 g++ 中编译? [复制]
【发布时间】:2016-01-06 14:12:53
【问题描述】:

我惊讶地发现 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("1\n");
        break;
    }

    case::TWO:
    {
        printf("2\n");
        break;
    }

    case::THREE:
    {
        printf("3\n");
        break;
    }

    default:
    {
        printf("default\n");
    }
    }
}

g++ 预处理器如何将“case”与“::ONE:”分开?

【问题讨论】:

    标签: c++ gcc g++


    【解决方案1】:

    g++ 预处理器如何将“case”与“::ONE:”分开?

    :: 解释为引用全局命名空间的不是预处理器,而是编译器。

    案例标签将被解析为

    case :: THREE :
    

    这完全没问题,因为您的 enum 值出现在全局命名空间 (::) 中。

    【讨论】:

    • 一旦 Cecilio 修复了 'root' 命名空间,你的答案就会重复;)
    • 我的意思是“解析器”,而不是“预处理器”。
    • @John 你必须准确地说,预处理器是另一回事。
    【解决方案2】:

    它不是预处理器。 C 编译器(它的标记器)将其视为:

    case :: ONE

    这在 C++ 中是可以的。 :: 运算符表示根命名空间。 C没有这样的东西。

    【讨论】:

    • 没有根命名空间,是全局命名空间。
    • “C 没有这样的东西”:因此它是 C++ 编译器,而不是 C 编译器 :)
    【解决方案3】:

    你有一个简单的枚举,而不是一个作用域枚举(参见:enum class)。普通枚举位于根范围内,因此您可以编写 ::ONE

    使用作用域枚举,您可以执行以下操作:

    enum class Scoped { FIRST, LAST = 9};
    //...
    case Scoped::FIRST : //...
    

    即使您不在 case 关键字和枚举数之间留下空格,g++ 中的标记器(因为这是 C++ 功能)也可以解析。

    【讨论】:

      【解决方案4】:

      在编译过程的lexical analysis 阶段,程序文件中的字符流被转换为标记。这里使用的流行算法之一是maximal munch,其中最长匹配的合法令牌被视为预期令牌。在此示例中,它将case::ONE: 分解为case::ONE:

      也有一些缺点:x = y/*z 是一个错误,因为/* 是最长匹配的合法令牌,而用户可能想说x = y / *z。你可以找到很多这样奇怪的例子,其中几个是herehere

      【讨论】:

        猜你喜欢
        • 2017-04-26
        • 2016-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-01
        • 2021-04-04
        • 1970-01-01
        相关资源
        最近更新 更多