2013-01-22 25 views
0

我讀過的主題,文章和SO答案的#define值沒有類型,我已經決定了這個概念,認爲類型是容器變量的屬性,而不是值的屬性本身:斷言值文字沒有類型是錯誤的?

const char cVALUE = 100; // 'cVALUE' is char with value 100, wich type is '100'? 
const short sVALUE = 100; // 'sVALUE' is short with value 100, wich type is '100'? 
const int iVALUE = 100;  // 'iVALUE' is int with value 100, wich type is '100'? 
#define VALUE 100   // wich type is 'VALUE'? 

但是,怎麼樣value suffixes

#define VALUE_L 100l // 'VALUE_L' is long? 
#define VALUE_UL 100ul // 'VALUE_UL' is unsigned long? 
#define VALUE_LL 100ll // 'VALUE_LL' is long long? 
#define VALUE_ULL 100ull // 'VALUE_ULL' is unsigned long long? 

在上面的代碼中,類型似乎附着的價值,所以這一切的原始值類型的值,而不是什麼我以前讀。但還有更多!文本文字甚至有限定詞,例如:

#define TEXT "Text" // '"Text"' is an array of some kind of chars. 

#define文本值以上的類型是(字符類型,如果你使用MSVC工作,我認爲字符類型可以改變改變project settings -> Character set,沒有想法,如果它可能在另一個IDE)它也有const cualifier,它是一個LValue而不是一個RValue,數字和文字文字之間的所有這些行爲差異擾亂了我。

因此,假設字符類型是char,字面"Text"的類型是const char *const char * constconst char[5]?或者至少,在上下文中推導出正確類型之前,它根本沒有類型?

而且,在C++ 11標準,該文本文字也可以使用一些prefixes,設置字符集的類型爲:

#define TEXT L"Text" // wide string with char type wchar_t 
#define TEXTu8 u8"Text" // UTF-8 string with char type char 
#define TEXTu u"Text" // UTF-16 string with char type char16_t 
#define TEXTU U"Text" // UTF-32 string with char type char32_t 

想着這一切的東西后,我很迷茫,於是我懇求一些建議:

  • 爲什麼常識是文字值(和#define s)沒有類型,但可以用文字指定類型?換句話說:斷言值文字沒有類型是錯誤的?
  • 值文字沒有後綴和沒有小數(如100),總是可以考慮類型int?
  • 哪些是文字文字的類型和限定符,甚至考慮它的前綴?
+1

問題在於你的前提。你用#值來定義'#define',但它們不是這樣的。它們是宏。 'VALUE'在C++中沒有輸入。 '100'的類型爲'int'。 – GManNickG

+1

也可以考慮宏像'#define FOO 0f,0U'。假設宏有一個類型(一種類型),那麼會是什麼類型? – MSalters

+0

@MSalters取決於逗號運算符的行爲和'FOO'的位置:'unsigned int a = FOO;'和'void f(float f,unsigned int i); f(FOO)'會產生不同的行爲。 –

回答

2

爲什麼常見的知識是文字值(和#defines)沒有類型,但類型可以用文字指定?換句話說:斷言值文字沒有類型是錯誤的?

不是。文字都有類型,正如C++ 11標準的第2.14節所規定的那樣。在解釋文字之前,預處理器宏被替換。

沒有後綴和沒有小數(如100)的值字面值總是可以考慮爲int類型嗎?

否;十進制文字是可以代表該值的第一個intlong intlong long int。如果需要,八進制或十六進制文字也可以是無符號的。 2011年之前,long long未被考慮,因爲它不是標準類型。

所以100將有int類型,因爲它足夠小,可以由int表示。

哪個是文本文字的類型和限定符,甚至考慮它的前綴?

沒有前綴,它是一個數組const char,它足夠大以容納所有字符和零終止符。所以"Text"有型號char const[5]

使用前綴時,字符類型將更改爲您在問題中提供的類型;數組大小仍然足夠大,包括終止符在內的所有字符。

+0

幾乎所有的答案都幫助我澄清了我對#define和字面值的理解,但是這個問題關注我提出的問題。 –

0

#define告訴預編譯器與所述定義來代替所有實例,所以類型不是在可變顯式的,但它可以通過查看它代表的文本值來確定。

  • 的字面整數是無任何改性劑的int,或者可以做成一個long等像436234636L。
  • 字符串文字是一個普通的字符串,除非在你的問題中附加了修飾符。
4

在C和C++中,預處理器和編譯器是兩個獨立的實體。

處理#define和其他預處理器指令的預處理器沒有類型系統。它處理字符串。而且這些字符表示的任何值都留給編譯器本身。

考慮

#define Y x[ 

這是一個合法的預處理指令,即使串x[在C.沒有意義然而,你可以使用它作爲

char Y 10]; 

申報和char陣列x

事實上C預處理器可以在源文件被用於除C.其它語言例如,它通常被用於FORTRAN源。由於FORTRAN沒有標準的預處理器。

+0

因此,一個'#define'值沒有類型,只是一個字面值呢? –

+1

#define只定義文本替換。這與您在編輯器中用「替換別的東西」的鍵組合相同,但它也允許爭論和其他「聰明」的東西。 –

+2

@PaperBirdMaster有時在C中使用文字值可能會有誤。例如,通過函數重載,可以對'foo(1)'和'foo(1.0)'或'foo(1l)'進行不同的調用。對於這種情況,後綴有助於解決歧義。但後綴不能替代完整的語言類型系統。 –

0

當預處理器會看到文本#define VALUE 100,它存儲的字符串VALUE [或類似的東西],而「置換」爲100每當預處理器以後發現VALUE,它100替換它。因此,VALUE沒有類型。 C中的文字100確實有一種類型 - 它是int,因爲這就是語言的規則所說的。

記住,預處理器更換合適的編譯之前發生,所以preprocesor更換可以做的「怪異」萬事,是很難(或者有時是不可能的),而宏做。

再一次,預處理器簡單地將TEXT替換爲"Text",並且在那一點上它沒有類型。類型只存在於正確的編譯器中。所以,如果您有:

#define TEXT "Text" 

void myfun(int x) 
{ 
    ... 
} 

... 
myfun(TEXT); 

的預處理會產生

... 
myfun("Text"); 

只有當你的代碼的正確編譯,將編譯器發現,「嗯,這是一個文本字符串,它不是如預期的整數「,並給你一些錯誤。

至於的"Text"「類型」,它不依賴於確切的上下文。在大多數情況下,安全的做法是將其視爲const char *,但在某些情況下,它也可以被認爲是char [5]

2

首先,你的問題:

斷言值文字沒有類型是假的?

是的。

沒有後綴和沒有小數(如100)的值字面值總是可以考慮爲int類型嗎?

我認爲默認情況下,您得到類型int

究竟是文本文字的類型和cualifiers,甚至考慮它的前綴?

如果我沒記錯的話,默認的類型是char []

其次,一些背景:

值文字一個類型 - 它只是它沒有明確規定,而不是所有的類型都可以指定方式。

通過聲明常量,您可以明確指定類型併爲編譯器提供更多信息。

考慮以下因素:

#define VALUE1 102 

會告訴你,你的價值是一個int文字。

通過聲明一個常量,你可以說:

static const int VALUE1 = 102; 
static const float VALUE1 = 102; 
static const double VALUE1 = 102; 
static const unsigned int VALUE1 = 102; 

正確的/更好的方式做define(正確的是使用define爲常數相對而言)是:

#define VALUE1 (int(102)) 
#define VALUE1 (float(102)) 
// etc ... 

在這一點上,你最好添加常量。

+0

+1用於指定文字類型的非歧義方式。 –

+0

'static const int Value1 = 102'和'#define VALUE2 102'給編譯器提供了完全相同的類型信息。在每種情況下,指定的值都是一個int。類似地,對於'102.0f'(float),'102.0'(double)等等。很少有需要使用轉換來指定文字的類型。 –

+0

@PeteBecker,即使他們提供相同的信息,仍然存在問題,因爲您希望能夠將其視爲變量。例如,您可以在調試器中跟蹤常量的值,但不是文字。使用文字('define'),您可以在源代碼中看到已定義的標籤,但調試器不理解如何跟蹤該標籤(因爲標籤上的信息在預編譯器中被刪除,編譯器沒有找到它)。 – utnapistim

2

它們是正確的,因爲預處理器沒有類型。你的

#define VALUE_L 100l 

例如這並不意味着VALUE_L具有類型long。您可以使用預處理器將該文本插入字符串文本的中間,例如this

宏沒有類型。預處理器可以創建令牌,然後編譯器可以將其解釋爲具有類型 - 但這是正切的,它不必做任何這樣的事情。

另外,L""文字是C++ 03和wchar_t。文字""的類型爲const char[1],並且是一個左值。它們是左值的原因是因爲傳統上它們被指向const char*,並且該指針必須指向左值,否則在有用之前它將變爲無效,而傳統的C數組不能爲右值。

+0

「_您可以使用預處理器將該文本插入到字符串literal_中間。」您怎麼能做到這一點? [我試過](http://ideone.com/VSWsTz)沒有成功。 –

+0

@PaperBirdMaster:我認爲他的意思是生成一個字符串文字:http://ideone.com/akyOup。一旦有東西是字符串文字,就不能使用預處理器對其語法結構做任何事情,它只是一個單一的標記。 – GManNickG

+0

使用[this](http://ideone.com/4L6b2x)。 – Puppy

1

#define是預處理器的指令,它只是複製和粘貼樣式替換。預處理器不知道或關心代碼的含義,也沒有關於類型的概念。

預處理後,編譯器處理表達式,語句,類型等。每個表達式(除非它是重載函數的名稱或地址)具有僅取決於該表達式的類型,而不取決於代碼的上下文。

(C++ 11的支撐-INIT-名單沒有類型,而不是技術上的表達,雖然他們可以在許多相同的上下文的出現。)

所以#define VALUE 100有意義的預處理,但在這一點上,類型的想法甚至不適用。但幾乎任何正確使用VALUE之後都會將其用作表達式,並且這些表達式都將具有類型int

是的,數字後綴和字符串前綴確實會影響文字表達式的類型。 100的類型是int,但100UL的類型是unsigned long

字面"Text"總是有類型const char [5],但char的確切含義和表示形式可以取決於您的編譯器。在大多數情況下,該文字將立即使用隱式數組到指針轉換衰減到const char*類型。 (另外,對於從const發明之前用古C代碼的向後兼容性,C++允許從一個字符串初始化char*可變,但最好不要讓這種情況發生。)

類似地,字面L"Text"具有類型const wchar_t [5] , 等等。