常量

常量 是值固定的表示式。

字面值

字面值是最明顯的常量型別。它們用於在程式的原始碼中表達特定值。我們在之前的章節中已經使用了一些字面值,用於給變數賦值或表達我們希望程式打印出來的訊息,例如,當我們寫下

1
a = 5;

這段程式碼中的 5 是一個 字面值常量

字面值常量可以分為:整數、浮點數、字元、字串、布林值、指標和使用者定義字面值。

整數數值


1
2
3
1776
707
-

這些是表示整數值的數值常量。請注意,它們不包含在引號或其他特殊字元中;它們是數字的簡單序列,代表十進位制表示的整數;例如,1776 始終代表值 一千七百七十六

除了十進位制數(我們大多數人每天使用的數字)之外,C++ 還允許使用八進位制數(基數為 8)和十六進位制數(基數為 16)作為字面值常量。對於八進位制字面值,數字前會加上一個 0(零)字元。對於十六進位制,它們的前面是 0x(零,x)字元。例如,以下字面值常量都等價於

1
2
3
75         // decimal
0113       // octal
0x4b       // hexadecimal  

所有這些都代表相同的數字:75(七十五),分別表示為十進位制、八進位制和十六進位制數值。

這些字面值常量就像變數一樣,也有型別。預設情況下,整數字面值是 int 型別。但是,可以在整數字面值後附加某些字尾來指定不同的整數型別

字尾型別修飾符
u Uunsigned
l Llong
ll LLlong long

unsigned 可以與另外兩個中的任何一個以任何順序組合,形成 unsigned longunsigned long long

例如:

1
2
3
4
5
75         // int
75u        // unsigned int
75l        // long
75ul       // unsigned long 
75lu       // unsigned long 

在以上所有情況下,字尾都可以使用大寫或小寫字母指定。

浮點數數值

它們表示實數值,帶有小數和/或指數。它們可以包含小數點、e 字元(表示“乘以 10 的 X 次方”,其中 X 是跟在 e 字元後面的整數值),或者同時包含小數點和 e 字元。

1
2
3
4
3.14159    // 3.14159
6.02e23    // 6.02 x 10^23
1.6e-19    // 1.6 x 10^-19
3.0        // 3.0  

這四個是 C++ 中有效的帶小數的數字。第一個數字是 PI,第二個是阿伏伽德羅數,第三個是電子的電荷(一個極小的數)- 所有這些都是近似值 -,最後一個數字是 ,表示為浮點數字面值。

浮點數字面值的預設型別是 double。可以透過新增以下字尾之一來指定 floatlong double 型別的浮點數字面值

字尾型別
f Ffloat
l Llong double

例如:

1
2
3.14159L   // long double
6.02e23f   // float  

浮點數字面常量中可能用到的字母(efl)中的任何一個都可以使用小寫或大寫字母編寫,含義沒有區別。

字元和字串字面值

字元和字串字面值包含在引號中。

1
2
3
4
'z'
'p'
"Hello world"
"How do you do?"

前兩個表示式表示單字元字面值,後兩個表示由多個字元組成的字串字面值。請注意,要表示單個字元,我們將其放在單引號(')之間;要表示字串(通常由多個字元組成),我們將字元放在雙引號(")之間。

單字元和字串字面值都需要引號包圍,以將它們與可能的變數識別符號或保留關鍵字區分開。請注意這兩個表示式之間的區別

x
'x'

在這裡,單獨的 x 指的是一個識別符號,例如變數名或複合型別名;而 'x'(包含在單引號中)指的是字元字面值 'x'(代表小寫字母 x 的字元)。

字元和字串字面值還可以表示難以或不可能在程式原始碼中以其他方式表達的特殊字元,如換行符(\n)或製表符(\t)。所有這些特殊字元前面都帶有反斜槓字元(\)。

這裡是單字元轉義碼的列表

轉義碼描述
\n換行
\r回車
\t製表符
\v垂直製表符
\b退格
\f換頁符
\a響鈴(蜂鳴)
\'單引號('
\"雙引號("
\?問號(?
\\反斜槓(\

例如:

'\n'
'\t'
"Left \t Right"
"one\ntwo\nthree"

在內部,計算機將字元表示為數字程式碼:最典型的是,它們使用 ASCII 字元編碼系統的一種擴充套件(有關更多資訊,請參閱 ASCII 碼)。字元也可以在字面值中使用其數字程式碼表示,方法是寫入一個反斜槓字元(\),後跟以八進位制(基數為 8)或十六進位制(基數為 16)表示的程式碼。對於八進位制值,反斜槓後面直接跟著數字;而對於十六進位制,則在反斜槓和十六進位制數字本身之間插入一個 x 字元(例如:\x20\x4A)。

可以透過將多個字串字面值用一個或多個空白字元(包括製表符、換行符和其他有效空白字元)分隔來將它們連線成一個字串字面值。例如

1
2
"this forms" "a single"     " string "
"of characters"

上面的字串字面值等價於

1
"this formsa single string of characters"

請注意,引號內的空格是字面值的一部分,而引號外的空格則不是。

一些程式設計師還使用一個技巧來包含多行長字串字面值:在 C++ 中,行尾的反斜槓(\)被視為一個行續接字元,它將當前行和下一行合併為一行。因此,以下程式碼

1
2
x = "string expressed in \
two lines"

等價於

1
x = "string expressed in two lines"

以上所有字元字面值和字串字面值都由 char 型別的字元組成。可以透過使用以下任一字首來指定不同的字元型別

字首字元型別
uchar16_t
Uchar32_t
Lwchar_t

請注意,與整數字面值的型別字尾不同,這些字首是區分大小寫的char16_t 使用小寫,而 char32_twchar_t 使用大寫。

對於字串字面值,除了上述的 uUL 之外,還有兩個額外的字首

字首描述
u8字串字面值在可執行檔案中使用 UTF-8 編碼
R字串字面值是原始字串

在原始字串中,反斜槓、單引號和雙引號都是有效字元;字面值的內容由一個起始的 R"sequence(" 和一個結束的 ")sequence" 分隔,其中 sequence 是任何字元序列(包括空序列)。字串的內容是括號內的內容,忽略分隔序列本身。例如

1
2
R"(string with \backslash)"
R"&%$(string with \backslash)&%$"

以上兩個字串都等價於 "string with \\backslash"R 字首可以與任何其他字首結合使用,例如 uLu8

其他字面值

C++ 中存在三個關鍵字字面值:truefalsenullptr
  • truefalsebool 型別變數的兩個可能值。
  • nullptr空指標值。

1
2
3
bool foo = true;
bool bar = false;
int* p = nullptr;

型別化常量表達式

有時,為常量值命名是很方便的。

1
2
const double pi = 3.1415926;
const char tab = '\t';

然後,我們可以使用這些名稱來代替它們被定義的字面值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
using namespace std;

const double pi = 3.14159;
const char newline = '\n';

int main ()
{
  double r=5.0;               // radius
  double circle;

  circle = 2 * pi * r;
  cout << circle;
  cout << newline;
}
31.4159

預處理器定義 (#define)

命名常量值的另一種機制是使用預處理器定義。它們的格式如下

#define 識別符號 替換內容

在此指令之後,程式碼中 identifier 的任何出現都將被解釋為 replacement,其中 replacement 是任何字元序列(直到行尾)。此替換由預處理器執行,並在程式編譯之前發生,從而導致一種盲目替換:涉及的型別或語法的有效性不會以任何方式進行檢查。

例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
using namespace std;

#define PI 3.14159
#define NEWLINE '\n'

int main ()
{
  double r=5.0;               // radius
  double circle;

  circle = 2 * PI * r;
  cout << circle;
  cout << NEWLINE;

}
31.4159

請注意,#define 行是預處理器指令,因此它們是單行指令,與 C++ 語句不同,不需要在末尾加分號(;);指令會自動擴充套件到行尾。如果行中包含分號,它將成為替換序列的一部分,並且也會包含在所有被替換的出現中。
Index
目錄