1、算術(shù)運算符
C++當(dāng)中提供5種基礎(chǔ)的算術(shù)運算符:加法
、減法
、乘法
、除法
和取模
。
我們來看下代碼:
1
2
3
4
5
6
7
|
int a = 10, b = 3; cout << a + b << endl; // 13 cout << a - b << endl; // 7 cout << a * b << endl; // 30 cout << a / b << endl; // 3 cout << a % b << endl; // 1 |
前面三個都非常簡單,著重講下最后兩種。
對于除法來說,我們要注意的是它是區(qū)分類型的。當(dāng)我們的除數(shù)和被除數(shù)都是整數(shù)的時候,得到的結(jié)果也會是一個整數(shù)。所以10 ? 3
得到的結(jié)果就是3,它的小數(shù)部分會被拋棄。想要得到小數(shù)結(jié)果,只需要除數(shù)或者被除數(shù)當(dāng)中有一個是浮點型即可。
取模運算符求的就是一個數(shù)除以另外一個數(shù)之后的余數(shù)。這里要注意,在其他語言當(dāng)中并沒有對取模運算的限制,而在C++當(dāng)中,嚴格限制了取模運算的對象只能是整數(shù)。
否則編譯的時候會報錯:
2、優(yōu)先級
C++當(dāng)中算術(shù)運算符的優(yōu)先級和我們從小數(shù)學(xué)課本里是一樣的,先乘除再加減。
如:
1
2
3
|
3 + 4 * 5; // 23 120 / 4 * 5; // 150 20 * 5 + 4 * 6; // 124 |
即當(dāng)乘除法和加減法同時出現(xiàn)時,先算乘除后算加減。如果有多個運算符同樣優(yōu)先級,那么先左后右。
3、類型轉(zhuǎn)換
前面說了,同樣是除法,根據(jù)除數(shù)和被除數(shù)類型的不同,得到的結(jié)果也不同。這樣固然非常靈活,但是除了更加復(fù)雜給學(xué)習(xí)、使用者帶來負擔(dān)之外,也會使得計算機的操作更加復(fù)雜。
比如我們一共有11種整型和3種浮點型,那么我們在計算的時候就會出現(xiàn)大量不同的情況。比如short + short
,short + int
,short + double
等等,那么編譯器就需要對這么多種情況都進行處理,這顯然是非常麻煩的。為了解決這個問題,C++會自動執(zhí)行許多類型轉(zhuǎn)換。
下面我們對這些情況進行一一討論。
初始化和賦值時的轉(zhuǎn)換
當(dāng)我們對某個值進行初始化或者賦值的時候,C++會自動將賦予的值轉(zhuǎn)化成接收者的類型。
比如:
1
2
|
float a = 3.5f; double b = a; |
在上面這個例子當(dāng)中,我們將一個float
類型的變量a賦值給了double
類型的b。那么編譯器會將a的值拓展成64位的double再賦值給b。也就是說不會影響b的類型。
這樣將長度更短的變量轉(zhuǎn)化成更長變量的類型轉(zhuǎn)換除了多占用一點內(nèi)存之外,不會導(dǎo)致什么問題。但反向操作可能就會出錯,
比如:
1
2
|
long long a = 0x3f3f3f3f3f3f3f; int b = a; |
在上面的例子當(dāng)中,我們將一個long long
賦值給了int,由于a的數(shù)值非常大超過了int
能夠承載的范圍,進行這樣的賦值之后,編譯器并不會報錯(甚至不會有警告),但將會導(dǎo)致結(jié)果錯誤。b變量將不可能再和a變量相等。
再比如將float
變量賦值給int
的時候,同樣也會有類似的問題,所以在進行賦值的時候,當(dāng)兩個變量的類型不同時,千萬要當(dāng)心。
使用花括號進行轉(zhuǎn)換
這是C++ 11
的新特性,使用大括號進行初始化,這種操作被稱為列表初始化。
這種方式的好處和壞處都很明顯,好處是它不允許變量長度縮窄的情況,壞處則是又增加了學(xué)習(xí)的成本。例如,不允許將浮點型轉(zhuǎn)換成整型。在不同的整型之間以及整型轉(zhuǎn)化成浮點型的操作可能被允許,取決于編譯器知道目標(biāo)變量能夠正確地存儲賦給它的值。比如可以將int類型賦值給long
,因為long
總是至少與int
一樣長,反向操作則會被禁止。
1
2
3
4
5
|
int a = 0x3f3f3f3f; long b = {a}; // 允許 long a = 0x3f3f3f3f; int b = {a}; // 禁止 |
關(guān)于列表初始化,C++ primer
當(dāng)中還列舉了一個非常有意思的case
:
1
2
3
4
5
6
7
8
9
10
11
|
const int x = 55; char c = {x}; // 允許 int x = 55; char c = {x}; // 禁止 const int x = 1255; char c = {x}; // 禁止 const int x = 1255; char c = x; // 允許會警告 |
這是為什么呢?因為我們加了const
修飾之后,編譯器就明確知道了x的值,就等于55,它在char
類型的范圍內(nèi),所以允許將它轉(zhuǎn)化成char
。如果不加const
,那么在編譯器看來x是一個int型的變量,它的范圍要大于char
,所以會禁止。即使我們加了const
修飾,如果x的值過大,超過char
的范圍,也同樣會被禁止。
4、表達式中轉(zhuǎn)換
當(dāng)一個表達式當(dāng)中出現(xiàn)多個變量類型的時候,C++也會進行轉(zhuǎn)換。由于可能涉及的情況非常多,使得這個轉(zhuǎn)換的規(guī)則也會比較復(fù)雜。
表達式時C++
會將bool
、char
、unsigned char
、signed char
和short
全部轉(zhuǎn)換為int
對于bool
類型來說,true
會被轉(zhuǎn)化成1,false
轉(zhuǎn)換成0,其他類型的轉(zhuǎn)換應(yīng)該都很好理解,都是將范圍更小的變量轉(zhuǎn)化成范圍更大的int
,這種轉(zhuǎn)換稱作整型提升。因為通常int類型都是計算機最自然的類型,也意味著計算機在處理int的時候,處理的速度最快。
將不同類型進行運算的時候,也會做一些轉(zhuǎn)換。比如將int
和float
相加的時候,由于涉及到兩種類型,其中范圍較小的那個會被轉(zhuǎn)換成較大的類型。比如如果我們計算9.0 / 5,那么編譯器會先將5轉(zhuǎn)化成5.0,再進行除法運算,這樣得到的結(jié)果自然也是一個double
。
C++11的規(guī)范中除了一個類型轉(zhuǎn)換的校驗表,我們可以參考一下校驗表理解一下類型轉(zhuǎn)換的過程。
-
如果有一個數(shù)類型是
long double
,則將另外一個數(shù)也轉(zhuǎn)成long double
-
否則,如果有一個數(shù)類型是
double
,則將另外一個數(shù)也轉(zhuǎn)成double
-
否則,如果有一個數(shù)類型是
float
,則將另外一個數(shù)也轉(zhuǎn)成float
- 否則說明所有操作數(shù)都是整數(shù),執(zhí)行整型提升
5、強制類型轉(zhuǎn)換
C++當(dāng)中允許開發(fā)者手動強制對變量的類型進行轉(zhuǎn)換,這也是C++
的設(shè)計思路,規(guī)則嚴謹,但也允許推翻規(guī)則追求靈活度。
強制類型轉(zhuǎn)換的方式有兩種寫法:
1
2
3
|
int a; ( long ) a; long (a); |
這兩行代碼都是將一個int
型的a
轉(zhuǎn)換成long
型的,上面的是C語言的寫法,底下一行是C++的寫法。
還有一點要注意就是轉(zhuǎn)換的順序,我們來看一個例子:
1
2
3
4
|
int a = 11.99 + 19.99; cout << a << endl; int b = int (11.99) + int (19.99); cout << b << endl; |
在這段代碼當(dāng)中a和b輸出的結(jié)果是不同的,a輸出的結(jié)果是31,而b是30。
這是因為第一行代碼是先計算的加法,得到31.98
,再通過類型轉(zhuǎn)換將31.98轉(zhuǎn)換成int。對于浮點數(shù)向整型的轉(zhuǎn)換,C++會直接抹掉小數(shù)部分,所以得到的結(jié)果是31。而第二行代碼當(dāng)中,我們是先進行的類型轉(zhuǎn)換,11.99和19.99分別被轉(zhuǎn)換成了11和19,相加得到的結(jié)果也就是30了。
這里的一點差別很多新人經(jīng)常踩坑,千萬注意。
到此這篇關(guān)于C++算術(shù)運算符與類型轉(zhuǎn)換的文章就介紹到這了,更多相關(guān)C++算術(shù)運算符與類型轉(zhuǎn)換內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
注:文章轉(zhuǎn)自微信公眾號:Coder梁(ID:Coder_LT)