C++有兩種常量:文字常量和符号常量。這篇我們講文字常量。
文字常量:
文字常量(常被稱為常量)是直接插入到代碼中的值。他們是常量是以你不能更改他得值。
return 5; // 5 is an integer literal
bool myNameIsAlex = true; // true is a boolean literal
std::cout << 3.4; // 3.4 is a double literal
就像每個變量都有一個類型一樣,常量也會有一個類型,通常是根據它的值來假定的。
Literal value | Examples | Default type |
---|---|---|
integral value | 5, 0, -3 | int |
boolean value | true, false | bool |
floating point value | 3.4, -2.2 | double (not float)! |
char value | ‘a’ | char |
C-style string | “Hello, world!” | const char[14] (see chapter 6) |
文字常量字尾
如果預設的類型不符合你的期望,你可以使用字尾:
Data Type | Suffix | Meaning |
---|---|---|
int | u or U | unsigned int |
int | l or L | long |
int | ul, uL, Ul, UL, lu, lU, Lu, or LU | unsigned long |
int | ll or LL | long long |
int | ull, uLL, Ull, ULL, llu, llU, LLu, or LLU | unsigned long long |
double | f or F | float |
double | l or L | long double |
一般來說對整型沒有必要通過字尾來判斷,但是也有一些例子:
unsigned int value1 = 5u; // 5 has type unsigned int
long value2 = 6L; // 6 has type long
一般來說浮點數常量預設類型是double,如果想要變成float類型,需要增加f字尾:
float f = 5.0f; // 5.0 has type float
新的程式員往往會困惑,為什麼下面的程式并不按照期望的那樣顯示:
float f = 4.5;
這是因為4.5是沒有字尾的,是以是double類型的,而不是float類型。當C++定義常量類型時,他不會關心你用常量做什麼。是以你必須将4.5增加字尾,轉換成float類型,這樣會減小精度值。
C++也支援字元型常量:
std::cout << "Hello, world!" // "Hello, world!" is a C-style string literal
std::cout << "Hello," " world!" // C++ will concatenate sequential string literals
字元型常量在C++中處理起來非常奇怪。目前來說,将該常量作為輸出std::out的參數是可以了。但是不能把它當作參數傳遞給函數。要麼不會工作,要麼不會想你期望的那樣工作。後面我們會讨論C-style的字元串,以及怎麼解決這些奇怪的問題。
隻要意思明确,字元型常量是可以在C++中正常使用的,這往往會用在初始化一個值,進行數字運算,或者需要列印一個值的時候。
科學記數法的浮點類型
浮點常量的兩種類型:
double pi = 3.14159; // 3.14159 is a double literal in standard notation
double avogadro = 6.02e23; // 6.02 x 10^23 is a double literal in scientific notation
當然第二種類型的指數可以是負數:
double electron = 1.6e-19; // charge on an electron is 1.6 x 10^-19
八進制和十六進制常量
在日常的生活中,我們的數字都是由:0,1,2,3,4,5,6,7,8,9組成的,我們叫做十進制數值。在這個系統中我們可以這樣:0,1,2,3,4,5,6,7,8,9,10,11,12......通常來說,預設數值是10進制的。
int x = 12; // 12 is assumed to be a decimal number
在2進制中隻有0和1,所有的數字都是0和1組成的:0,1,10,01,1010101等
在計算機中還有兩種其他的進制類型:8進制和十六進制。
Decimal | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
Octal | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 |
如果要使用8進制,需要在前面增加一個0:
#include <iostream>
int main()
{
int x = 012; // 0 before the number means this is octal
std::cout << x;
return 0;
}
輸出為:10
8進制幾乎不使用,建議忽略。下面是16進制的介紹;
Decimal | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
Hexadecimal | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | 10 | 11 |
使用16進制需要在字首增加0x
#include <iostream>
int main()
{
int x = 0xF; // 0x before the number means this is hexadecimal
std::cout << x;
return 0;
}
輸出是15
因為在16進制中我們有16個不同的值來表示,正好4bits。通常來說兩個16進制的數就可以表示一個byte了。
考慮一個三十二位的整型數值:0011 1010 0111 1111 1001 1000 0010 0110。因為數字的重複和長度,非常難記和讀。但是用16進制表示就是:3A7F 9826.這說明16進制在記憶體中是一種間接的計數方式。是以16進制往往會用來表示位址值和未處理的資料值。
在C++14之前,沒有辦法直接配置設定二級制的資料,是以16進制給我們提供了一種的方式:
#include <iostream>
int main()
{
int bin(0);
bin = 0x01; // assign binary 0000 0001 to the variable
bin = 0x02; // assign binary 0000 0010 to the variable
bin = 0x04; // assign binary 0000 0100 to the variable
bin = 0x08; // assign binary 0000 1000 to the variable
bin = 0x10; // assign binary 0001 0000 to the variable
bin = 0x20; // assign binary 0010 0000 to the variable
bin = 0x40; // assign binary 0100 0000 to the variable
bin = 0x80; // assign binary 1000 0000 to the variable
bin = 0xFF; // assign binary 1111 1111 to the variable
bin = 0xB3; // assign binary 1011 0011 to the variable
bin = 0xF770; // assign binary 1111 0111 0111 0000 to the variable
return 0;
}
在C++14之後,可以用0b來表示:
#include <iostream>
int main()
{
int bin(0);
bin = 0b1; // assign binary 0000 0001 to the variable
bin = 0b11; // assign binary 0000 0011 to the variable
bin = 0b1010; // assign binary 0000 1010 to the variable
bin = 0b11110000; // assign binary 1111 0000 to the variable
return 0;
}
因為長整形非常難記,是以可以用'分開:
#include <iostream>
int main()
{
int bin = 0b1011'0010; // assign binary 1011 0010 to the variable
long value = 2'132'673'462; // much easier to read than 2132673462
return 0;
}
幻數,為什麼他們不好
考慮如下的小段:
int maxStudents = numClassrooms * 30;
像上面的30被稱為幻數,幻數就是在一段代碼中直接寫死的數字,并且沒有任何注釋。30是什麼意思?及時在這種情況下你可以猜到表示的是一個班級的最大數量,但是始終是不明确的。在更加複雜的情況下,你是沒有辦法猜到這個數字代表什麼意思的,除非有注釋。
使用幻數是一種非常差的體驗,除了沒有備注之外,值的修改也會非常麻煩。假設學校讓購買課桌,而現在美分班級最大的認數變成了35,在程式裡需要展現出來。考慮下面的情況:
int maxStudents = numClassrooms * 30;
setMax(30);
為了将程式中的size擴充到35,你需要更改。但是setMax中的30和這個30是否是同一個意思?這個setMax中的30需不需要更改?如果都是表示的班級人數,那麼就應該一起修改;如果不是,那麼需要保留。如果你是通過全部替換修改,那麼setMax中的30也會被改變。如果一個個去查找驗證的話,那麼就需要花費大量的時間。這都是非常不好的習慣。
下一篇文章我們會學習怎麼來很好地規避這個問題。