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 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
Octal | 0 | 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 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
Hexadecimal | 0 | 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也會被改變。如果一個個去查找驗證的話,那麼就需要花費大量的時間。這都是非常不好的習慣。
下一篇文章我們會學習怎麼來很好地規避這個問題。