2016-01-06 93 views
3

我很驚訝地得知,G ++(4.9)的編寫本(而GCC不會):爲什麼「case :: LABEL:」在g ++中編譯?

#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 ++預處理器能夠在 「案例」 從分開 「:: ONE:」?

回答

4

g ++預處理器如何能夠將「case」與「:: ONE:」分開?

它不是預處理器,而是編譯器,它將::解釋爲引用全局名稱空間。

的情況下,標籤會被解析爲

case :: THREE : 

,這就是完全確定,因爲你的enum值出現在全局命名空間(::)。

+0

一旦Cecilio修復了'root'命名空間,您的答案將變成重複;} – SergeyA

+0

我的意思是說「parser」,而不是「預處理」。 – John

+0

@John你必須確切地說,預處理器是另一回事。 –

3

它不是預處理器。 C編譯器(其標記生成器)看到,作爲:

case :: ONE

這是C++的確定。 ::運算符表示根名稱空間。 C沒有這樣的事情。

+1

沒有根名稱空間,它是一個全局名稱空間。 – SergeyA

+0

「C沒有這樣的事情」:因此它是C++編譯器,而不是C編譯器:) – mikedu95

0

你有一個簡單的枚舉,而不是範圍枚舉(參見:enum class)。 Plain枚舉位於根範圍內,因此您可以編寫::ONE

隨着範圍的枚舉,你可以做到以下幾點:

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

在G ++(因爲這是一個C++功能)甚至可以解決,如果你不將case關鍵字和枚舉之間留出空格標記生成器。

0

在編譯過程的lexical analysis階段,程序文件中的字符流被轉換爲令牌。這裏使用的流行算法之一是maximal munch,其中最長的匹配法律令牌被認爲是預期的令牌。在這個例子中,它將case::ONE:分成case,::,ONE:

還有一些缺點:x = y/*z是一個錯誤,因爲/*是最長的匹配合法標記,而用戶可能想說x = y/*z。你可以找到很多這樣的好奇的例子,其中有幾個是herehere