在C++中,字面常量(literal constant)即無需定義可以直接寫出來的量。字面常量的值一望便知,但是他的數據類型往往不能被准確分辨(尤其是使用auto時)。
我們直接寫出來的有確定值的量就是字面常量,如114514
、3.12
、'a'
、1e30
等,那么42
的類型是什么?3.12
是單精度還是雙精度?這些都有明確的規定,一個字面常量的類型是由他的形式完全決定的。
1. 整數和浮點數的字面值
整數的字面值
即使沒有了解過,也很容易想到114514
肯定是int
類型。那1145141919
呢?超過了int
當然就是一個long long
類型了。C++里整數常量的類型就是int->long->long long
里能表示出它的尺寸最小的類型(顯然都是有符號(signed)型)。比如:
2147483547
是int
,而2147483648
就是long long
類型了,而不是unsigned int
。42
即使在short
范圍內,類型也為int
而不是short
。-2147483648
在int
范圍內,但是仍然是long long
(前面沒有提到過負號,實際上-
不在字面值之內,先判定了2147483648的類型再取了符號)1000000000000000000000000
如果這個數連long long
都裝不下怎么辦?某些編譯器可以繼續擴展到128位整數(__int128_t
,范圍\([-2^{127}, 2^{127})\)),如果更大的話,就不能通過編譯了。
不過八進制和十六進制的規則有些不一樣。八進制和十六進制常量可以不用負號而表示負數(如0x80000000
),這個時候他的類型會被判定為unsigned
而不是負值。也就是說,此時按照int->unsigned int->.....->long long->unsigned long long
取能表示為正數的最小類型。
浮點數的字面值
與short
和int
的關系類似,雖然float
更小,但是double
才是我們最常用的浮點數類型。在C++里無論時小數表示還是指數表示,無論有幾位有效數字,所有的浮點類型默認都是double
(如0.1
、.09878675645
、1e20
、3E-15
)。
手動指定字面值
如果我們需要1個long long
類型的0,或者double
存不下超長的浮點數,就可以在值的后面加上修飾符,手動指定字面值的類型。
-
u
或U
指定該值為無符號類型,比如2147483648u
是一個unsigned int
,-1U
也是一個“無符號的-1”(即4294967295), -
l
或L
指定類型為long
,ll
或LL
指定類型為long long
。如
long long a = 3, b = max(a, 0)
會出錯,因為a
是long long
而0
為int
導致參數不匹配,修改為b = max(a, 0ll)
即可。u
和ll
可以混用,即ull
和ul
表示無符號長整形。 -
f
或F
指定類型為float
,指數類型和小數類型都可以(如1e3f
、0.12F
)。 -
l
和L
也可以用於浮點,表示指定long double
類型。
當然你也可以使用類型轉換,但是略顯繁瑣。
2. 字符和字符串的字面值
C++中char類型一般以\([0, 128)\)的整數與ASCII字符相對應。單個ASCII字符的類型當然是char
(如'a'
表示char大小的字符a,即97)。
字面字符串則是一個常量字符數組const char[]
或const char*
(並不是string
)。在傳參時,如果將常量字符串傳入f(char *s)
中,並修改字符串的值,將引發錯誤。
手動指定字面值
' '
的類型都是char
,不能使用漢字等其他字符,如果要指定寬字符(wide char)的字面量。可以在前面加上u
(表示16位字符char16_t
)、U
(表示32位字符char32_t
)或L
(表示寬字符wchar_t
,在不同環境下為16位或32位),比如u'天'
。
(當然這只是啟用中文字符串的一個步驟,還需要一系列寬字符的工具才能實現中文操作)
3. 布爾字面值
布爾字面值只有兩種:true
和false
。
true
轉化為任意數時值為1,false
轉化為任意數時值為0
- 任意非0數轉化為
bool
時,只有原數等於0時變為false
,否則都為true
(不過浮點數的判定方法有點特殊,由於浮點數的等於是“近似相等”,如果double x=0.1+0.2-0.3
,在某些環境下x==0
為true
,但x
的實際值由於浮點誤差並不為0(非常接近0的一個數),如果有循環if (x) {}
將仍然執行,除非x的實際值真的是0(正0或負0),才不會執行)
4. 指針字面值
指針字面值只有一個,那就是空指針nullptr
。
我們知道nullptr
、NULL
和0
都可以初始化空指針,其中nullptr
是類似true
和false
的字面值關鍵字,而NULL
僅僅是定義在頭文件里宏,其含義就是“0”,也就是說與0
沒有區別。
那為什么要專門在C++11里弄一個nullptr
呢。因為nullptr
是“指針”,而單獨存在的0是“int”。類似之前提到的max問題
。如果有兩個同名函數f(int x)
和f(int *x)
,如果傳入f(NULL)
,由於NULL
的值為0,就會調用前者,要調用后者,則只能使用f(nullptr)
。