字面常量 (C語言)

字面常量。下述內容遵從C11與C++11語言標準。整型字面常量.包括下述的數值進位制：整型字面量轉化為整數型別表示，依照下述順序：其中，10進製表示的字面量僅考慮有符號的整數型別；而8進位制或16進位制的字面量先考慮能否用有符號的整數型別表示，如不能再考慮能否用同樣長度的無符號整數型別表示。例如，字面量0x87654321，這是一個正值，用4位元組長的int無法表示，編譯器就會自動選用unsigned int來表示該字面量。整型字面量可以使用字尾u U ul UL ull ULL明確表示各種無符號整型；使用字尾l L ll LL表示該字面量至少為long或為long long型。C++14引入了千分位分隔符。例如：auto integer_literal = 1'000'000;C++14還引入了二進位制字面量，例如：auto perm = 0b100110111;浮點型字面常量.包括下述的數值進位制：沒有後綴的浮點型字面量具有double型別。使用字尾 f F l L表示float或long double型別。C++14引入了千分位分隔符。例如：auto dd = 1'234.567'8;字元型字面常量.字元型字面量是用單引號括起來的一個或多個字元，可選字首字元有u、U、L。沒有字首字元的稱為普通字元字面量(ordinary character literal)或窄字元字面常量只包含執行字符集中一個可表示字元的普通字元字面量，如：'a'，則其型別為char，其值等於該字元在執行字符集中的編碼值。實際上，編譯器在token分析階段，通常就會把字元與字串在原始檔中的編碼串轉換為指定或者執行字符集的編碼串。包含多個字元的普通字元字面常量，被稱為多字元字面量中一個不可表示字元的普通字元字面量，被有條件支援，具有型別int，其值為實現定義。各常見C/C++編譯器一般都支援如下例子：// Multicharacter literalsint m0 = 'abcd'; // int, value 0x61626364需要注意的是，在C語言中字元常量'a'具有int型別，sizeof('a')等於sizeof(int)；在C++語言中字元字面量'a'具有char型別，sizeof('a')為1。使用字首L u U分別表示wchar_t char16_t char32_t等字元型別的字面量。例如codice_1。一個wchar_t型別的字面量的值，就是該字元在執行寬字符集中的編碼值；單如果該字元在執行寬字符集中不可表示，則其值是實現定義的。一個char16_t型別的字面量的值，就是該字元在Unicode編碼中的16位元的碼位；顯然該字元必須屬於Unicode中的基本多文種平面才能用16位元來編碼，否則程式是病態的。一個char32_t型別的字面量的值，就是該字元在Unicode編碼中的32位元的碼位。這些字元型別在x86平臺均為小端序表示。char16_t字面量或char32_t字面量，如果包含多個字元，是病態的。wchar_t 字面量，如果包含多個字元，其值是實現定義的。由於字元型字面量可能不屬於C/C++的token的字元範圍，這就需要用反斜線codice_2開始的轉義序列來表示一個字元值：上述兩種Unicode轉義序列的字元表示法，由編譯器自動轉換為相應的字元內部編碼格式。如為wchar_t字元。如果字元字面量的值超過了char、char16_t、char32_t、wchar_t實現定義的範圍，那麼其值是實現定義的。例如，原始檔是Latin-1編碼，執行字符集為utf-8，則codice_5中的字元值將被編譯器從Latin-1編碼的單位元組的0xD6自動轉為utf-8編碼的雙位元組的0xC3B6，在目標檔案與可執行檔案中字元c的值是'ö'的utf-8編碼值的最後一個位元組值即0xB6。為支援老的程式碼，C語言規定了三字元組替換，在掃描處理C語言原始檔時，替換下述的3字元出現為1個字元：如果希望在源程式中有兩個連續的問號，且不希望被預處理器替換，這種情況出現在字元字面常量、字串字面常量或者是程式註釋中，可選辦法是用字串的自動連線：codice_6或者轉義序列：codice_7。從Microsoft Visual C++ 2010版開始，該編譯器預設不再自動替換三字元組。如果需要使用三字元組替換，需要設定編譯器命令列選項/Zc:trigraphsgcc預設不識別三字元組，並會給出編譯警告。在指定了C/C++標準時，gcc才會識別三字元組，但仍會給出編譯警告。字串字面常量.C語言經典的ASCII-0字串，例如"Hello world!"。由codice_8 與 codice_9括起來的字串字面量叫做raw string literal，這可以避免大量使用反斜線跳脫字元造成的令人眼花繚亂的傾斜牙籤綜合徵，特別適用於定義正則表示式的模式字串時。例如：std::string filePath = R"(C:\Foo\Bar.txt)";std::regex re{ R"abc(s/"\([^"]*\)"/'\1'/g)abc" }; //如果字串包含了)"這兩個字元的組合，可選別的分界符，如codice_10。但這個分界符序列的長度最多16。字串字面量的值預設為工作字符集的編碼。使用編碼字首： u8 u U L 指出字串字面量的值為UTF-8、char16_t、char32_t、wchar_t的編碼序列。例如，char ss[]=u8"Hi世界";// ss陣列內儲存的是'H'、'i'、'世'、'界'這四個字元的UTF-8的編碼值相鄰的兩個字串將被編譯器自動連線為一個字串。如：char ss[]="Hello" " world.";列舉常量.列舉型別實質上是取有限個值的整型。根據C與C++98標準，列舉常量屬於定義了列舉型別的那個作用域，而不屬於這個列舉型別的內部作用域。C++發明人Bjarne Stroustrup稱之為列舉常量的作用域不受限現象，這會造成命名衝突，與列舉常量是“有型別的常量”的初衷不符，與面向物件程式設計的原則嚴重相悖。例如：enum FileAccess {Read = 0x1,Write = 0x2,FileAccess access = ::Read; // 正確FileAccess access = FileAccess::Read; // 錯誤enum FileShare {Read = 0x1, // 重定義錯誤Write = 0x2, // 重定義錯誤C++11為解決上述問題，引入了“列舉類”的。例如：enum class Color { RED, BLACK };Color c = Color::RED;C++11還允許指定列舉型別的儲存型別，這使得列舉型別的前向宣告成為可能。例如：enum class Color : char ; // forward declarationvoid foo (Color *p);// ...enum class Color : char { RED, BLUE }; // definition布林型字面常量.有兩個bool型別的字面常量：true false指標型字面常量.C++11定義了一個字面常量nullptr，其型別是std::nullptr_t。但std::nullptr_t既不是指標型別也不是到成員的指標型別。使用者定義的字面量.C++11新增加了使用者定義的字面常量，生成指定資料型別的物件。例如，struct S{int value;S operator ""_mysuffix(unsigned long long v) //使用者定義字面量運算子的實現S s_;s_.value=(int)v;return s_;int main()S sv;sv=101_mysuffix; //這裡的101是型別S的字面量std::cout«sv.value«std::endl;return 0;