在c++中,常量(constant)即新增了const的定義的量。字面常量(literal constant)即無需定義可以直接寫出來的量。字面常量的值一望便知,但是他的資料型別往往不能被準確分辨。而const作為常量關鍵字,則有著豐富的應用,同時可能導致的錯誤也讓人備受折磨。
我們直接寫出來的有確定值的量就是字面常量,如114514
、3.12
、'a'
、1e30
等,那麼42
的型別是什麼?3.12
是單精度還是雙精度?這些都有明確的規定,乙個字面常量的型別是由他的形式完全決定的。
整數的字面值
即使沒有了解過,也很容易想到114514
肯定是int
型別。那1145141919
呢?超過了int
當然就是乙個long long
型別了。c++裡整數常量的型別就是int->long->long long
裡能表示出它的尺寸最小的型別(顯然都是有符號(signed)型)。比如:
不過八進位制和十六進製制的規則有些不一樣。八進位制和十六進製制常量可以不用負號而表示負數(如0x80000000
),這個時候他的型別會被判定為unsigned
而不是負值。也就是說,此時按照int->unsigned int->.....->long long->unsigned long long
取能表示為正數的最小型別。
浮點數的字面值
與short
和int
的關係類似,雖然float
更小,但是double
才是我們最常用的浮點數型別。3.14
。在c++裡無論時小數表示還是指數表示,無論有幾位有效數字,所有的浮點型別預設都是double
(如0.1
、.09878675645
、1e20
、3e-15
)。
手動指定字面值
如果我們需要1個long long
型別的0,或者double
存不下超長的浮點數,就可以在值的後面加上修飾符,手動指定字面值的型別。
當然你也可以使用型別轉換,但是略顯繁瑣。
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'天'
。
(當然這只是啟用中文字串的乙個步驟,還需要一系列寬字元的工具才能實現中文操作)
布林字面值只有兩種:true
和false
。
指標字面值只有乙個,那就是空指標nullptr
。
我們知道nullptr
、null
和0
都可以初始化空指標,其中nullptr
是類似true
和false
的字面值關鍵字,而null
僅僅是定義在標頭檔案裡巨集,其含義就是「0」,也就是說與0
沒有區別。
那為什麼要專門弄乙個nullptr
呢。因為nullptr
是「指標」,而單獨存在的0是「int」。類似之前提到的max問題
。如果有兩個同名函式f(int x)
和f(int *x)
,如果傳入f(null)
,由於null
的值為0,就會呼叫前者,要呼叫後者,則只能使用f(nullptr)
。
用const
關鍵字定義的量叫常量,const
有很多方面的應用,這裡介紹其在定義變數時的一些擴充套件知識。
const int a = 5; //編譯時初始化
const int b = read(); //執行時初始化
const int c = sqrt(4)+a; //編譯時初始化
其中5
和sqrt(4)
被叫做常量表示式(const expression),他們是定製,並且可以在編譯時就直接得出答案,以此提公升效率。
但是在乙個複雜的程式裡,分辨乙個表示式能否作為常量表示式提前計算是一件困難的事,因此c++11裡出現了constexpr
。加上constexpr
表示我們希望它在編譯階段就初始化,編譯器將驗證表示式是否可以提前計算。
常量表示式的一般只由字面常量和字面常量初始化的常量組成。如果需要使用自定義函式,那麼必須是由constexpr宣告的,足夠簡單的常函式,以便在編譯時就計算出值。
對於一般的資料來講,const
修飾即代表這個值不能被修改,這叫做頂層const(toplevel const)。
然而對於指標來說,指標的值能否被修改和指標指向的值能否被修改是兩個獨立的問題。
const int a = 5;
const int *p = &a;//底層const
int* const p = &a;//頂層const
const int *const p = &a;//雙重
constexpr int* p = &a;//頂層const
當const
的位置不同時,其意義也不同。如果const
在*
的左側(與「int」的先後無所謂),代表*p
是常量,即p
的值可以修改到其他變數,但無論指向哪個變數都不能修改該變數,這叫做底層const(lowlevelconst)。p是乙個「指向常量的指標」
而const
在*
的右側時,可以理解為p
是常量,因此p
只能指向a
不能更改,但是可以通過p
修改a
的值。p是乙個「常量指標」。如果兩個同時使用,就變成了「指向常量的常量指標」。
不過使用constexpr
時的語法稍有不同,雖然這個關鍵字在*
左邊,但他代表的還是通常意義下的頂層const,即不能修改p的值。
對於乙個非常量,既可以用普通指標指向,也可以用「指向常量的指標」指向,此時不能通過指標修改變數值。
而引用的規則與指標相同。既可以使用普通引用,也可以使用常量引用,但是不能通過常量引用來修改值。
int a = 5;
const int &b = a;
int &c = a;
c = 3;
b = 3;// 錯誤
但是常量只能被「指向常量的指標」指向,也只能被常量引用繫結,當然也就不允許修改值了。
const int a = 5;
int &b = a;// 錯誤
int *p = &a;// 錯誤
當然你可以使用強制型別轉換來強制指向。
const int a = 5;
int *p = (const int*)&a;//或者使用const_cast
此時你甚至可以通過指標來修改變數值,不過這屬於未定義行為,取決於編譯器如何處理a
。 c 字面值常量
字面值常量 literal constant 字面值 是指只能用它的值稱呼它,常量 是指其值不能修改。每個字面值都有相應的型別,3.14是double型,2是int型。只有內建型別存在字面值。1.整形字面值規則 整形字面值常量可以用十進位制 八進位制 十六進製制表示。20 dec 024 oct 以...
C 字面值常量
乙個形如42的值被稱為字面值常量 literal 每個字面值常量都對應一種資料型別,字面值常量的形式和值決定了它的資料型別。字面值常量的型別有 1 整型字面值 整型字面值可以寫作三種形式 十進位制數 八進位制數和十六進製制數。以0開頭的整數代表八進位制數,以0x或0x開頭的代表十六進製制數。如下為數...
字面值常量
乙個形如 39 的值被稱作字面值常量 literal 每個字面值常量都對應一種資料型別,字面值常量的形式和值決定了它的資料型別。整型字面值寫作十進位制數 八進位制數或十六進製制數的形式。以0開頭的整數代表八進位制數,以0x或0x開頭的代表十六進製制數。下面的任意一種形式都表示數值 20 20 十進位...