- 現(xiàn)代C++編程:從入門到實(shí)踐
- (美)喬什·洛斯皮諾索
- 4702字
- 2024-04-15 11:40:42
2.1 基本類型
基本類型是最基本的對(duì)象類型,包括整數(shù)、浮點(diǎn)數(shù)、字符、布爾、byte、size_t和void。有些人把基本類型稱為原始類型或內(nèi)置類型,因?yàn)樗鼈兪呛诵恼Z(yǔ)言的一部分,幾乎總是使用的。這些類型可以在任何平臺(tái)上工作,但它們的特性,如大小和內(nèi)存布局,則取決于具體的實(shí)現(xiàn)。
基本類型取得了一種平衡。一方面,它們?cè)噲D映射從C++結(jié)構(gòu)到計(jì)算機(jī)硬件的直接關(guān)系;另一方面,它們簡(jiǎn)化了跨平臺(tái)代碼的編寫,允許程序員寫一次代碼就可以在許多平臺(tái)上運(yùn)行。下面的幾節(jié)將詳細(xì)介紹這些基本類型。
2.1.1 整數(shù)類型
整數(shù)類型存儲(chǔ)的是整數(shù)。四種大小的整數(shù)類型分別是short int、int、long int和long long int。每個(gè)類型都可以是有符號(hào)(signed)或無(wú)符號(hào)(unsigned)的。有符號(hào)變量可以是正數(shù)、負(fù)數(shù)或零,無(wú)符號(hào)變量必須是非負(fù)數(shù)。
整數(shù)類型默認(rèn)是有符號(hào)的int類型,這意味著我們可以在程序中使用簡(jiǎn)寫符號(hào)short、long和long long,而不是short int、long int和long long int。表2-1列出了所有可用的C++整數(shù)類型,展示了每種類型有無(wú)符號(hào),在不同平臺(tái)上的大小(以字節(jié)為單位),以及每種類型的格式指定符。
表2-1 整數(shù)類型及其大小和格式指定符

注意,不同平臺(tái)下整數(shù)類型的大小不同:64位Windows和Linux/Mac的long大小不同(分別為4字節(jié)和8字節(jié))。
通常情況下,編譯器會(huì)在格式指定符和整數(shù)類型不匹配時(shí)發(fā)出警告。但是,在printf語(yǔ)句中使用格式指定符時(shí),必須確保它們是正確的。這里列出格式指定符是為了讓你可以在后面的例子中向控制臺(tái)打印整數(shù)。
注意 如果想確保整數(shù)的大小,那么可以使用<cstdint>庫(kù)中的整數(shù)類型。例如,如果你需要一個(gè)正好是8、16、32或64位的有符號(hào)整數(shù),則可以使用int8_t、int16_t、int32_t或int64_t。你可以在這個(gè)庫(kù)中找到速度最快、最小、最大、有符號(hào)和無(wú)符號(hào)整數(shù)類型,以滿足各種要求。但由于這個(gè)頭文件并不總是在每個(gè)平臺(tái)上都可用,因此你應(yīng)該只在沒(méi)有其他選擇時(shí)使用cstdint類型。
字面量是程序中的硬編碼值。我們可以使用四種硬編碼的、整數(shù)字面量表示:
? 二進(jìn)制:使用前綴0b。
? 八進(jìn)制:使用前綴0。
? 十進(jìn)制:這是默認(rèn)的。
? 十六進(jìn)制:使用前綴0x。
這是同一組整數(shù)的四種不同寫法。例如,代碼清單2-1顯示了如何使用每一種非十進(jìn)制表示來(lái)賦值整數(shù)變量。
代碼清單2-1 給幾個(gè)整數(shù)變量賦值并以適當(dāng)?shù)母袷街付ǚ蛴∷鼈兊某绦?/b>


這個(gè)程序使用非十進(jìn)制表示整數(shù)(二進(jìn)制?、八進(jìn)制?和十六進(jìn)制?),并使用表2-1中列出的格式指定符將它們用printf打印出來(lái)。每個(gè)printf的輸出都顯示在代碼下方。
注意 整數(shù)字面量可以包含任何數(shù)量的單引號(hào)('),以方便閱讀。編譯器會(huì)完全忽略這些引號(hào)。例如,1000000和1'000'000都是表示一百萬(wàn)的字面量。
有時(shí),打印無(wú)符號(hào)整數(shù)的十六進(jìn)制表示或八進(jìn)制表示(較少見)是很有用的。我們可以使用printf格式指定符%x和%o實(shí)現(xiàn)這個(gè)目的,如代碼清單2-2所示。
代碼清單2-2 一個(gè)使用無(wú)符號(hào)整數(shù)的八進(jìn)制和十六進(jìn)制表示的程序

十進(jìn)制數(shù)3669732608的十六進(jìn)制表示是dabbad00,由于十六進(jìn)制格式指定符%x?,因此它出現(xiàn)在輸出的第一行。十進(jìn)制數(shù)69的八進(jìn)制表示是105。無(wú)符號(hào)整數(shù)的格式指定符%u?和八進(jìn)制整數(shù)的格式指定符%o?分別對(duì)應(yīng)于參數(shù)?和?。printf語(yǔ)句將這些量?替換到格式化字符串中,產(chǎn)生信息There are 69, 105 leaves here.。
警告 八進(jìn)制前綴是B語(yǔ)言的遺留問(wèn)題,可追溯到PDP-8計(jì)算機(jī)和八進(jìn)制無(wú)處不在的時(shí)代。C以及C++延續(xù)了這個(gè)可疑的傳統(tǒng)。例如,在對(duì)美國(guó)郵政編碼進(jìn)行硬編碼時(shí)必須小心:

去除十進(jìn)制數(shù)的前面的零;否則,它們將不再是十進(jìn)制數(shù)。這一行無(wú)法編譯,因?yàn)?不是八進(jìn)制數(shù)字。
默認(rèn)情況下,整數(shù)字面量的類型一般是int、long或long long。整數(shù)字面量的類型是這三種類型中最小的那種。這是由語(yǔ)言定義的,并將由編譯器強(qiáng)制執(zhí)行。
如果想更靈活,則可以給整數(shù)字面量提供后綴來(lái)指定它的類型(后綴不區(qū)分大小寫,所以你可以選擇自己最喜歡的風(fēng)格)。
? unsigned對(duì)應(yīng)后綴u或U。
? long對(duì)應(yīng)后綴l或L。
? long long對(duì)應(yīng)后綴ll或LL。
把unsigned后綴和long后綴或long long后綴結(jié)合起來(lái)可以指定整數(shù)類型的符號(hào)性和大小。表2-2顯示了后綴組合可能對(duì)應(yīng)的類型。允許的類型用復(fù)選標(biāo)記(√)表示。對(duì)于二進(jìn)制、八進(jìn)制和十六進(jìn)制字面量,可以省略后綴u或U。這些都用星號(hào)(*)來(lái)描述。
表2-2 整數(shù)后綴

允許的最小類型仍能表示整數(shù)字面量的類型就是最終類型。這意味著,在特定整數(shù)允許的所有類型中,最小的類型將被應(yīng)用。例如,整數(shù)字面量112114可以是int、long、long long類型的。由于int可以存儲(chǔ)112114,因此最終的整數(shù)字面量是int類型的。如果真的想采用long類型,則可以指定為112114L(或112114l)。
2.1.2 浮點(diǎn)類型
浮點(diǎn)類型存儲(chǔ)的是實(shí)數(shù)(在這里可以定義為任何帶有小數(shù)點(diǎn)和小數(shù)部分的數(shù)字,如0.33333或98.6)的近似值。雖然無(wú)法在計(jì)算機(jī)內(nèi)存中準(zhǔn)確地表示某些實(shí)數(shù),但可以存儲(chǔ)一個(gè)近似值。如果這看起來(lái)很難相信,那么可以想一想像π這樣的數(shù)字,它有無(wú)限多的位數(shù)。在有限的計(jì)算機(jī)內(nèi)存中,怎么可能表示無(wú)限多位的數(shù)字?
與所有其他類型一樣,浮點(diǎn)類型占用的內(nèi)存是有限的,這被稱為類型的精度。浮點(diǎn)類型的精度越高,它對(duì)實(shí)數(shù)的近似就越準(zhǔn)確。C++為近似值提供了三個(gè)級(jí)別的精度:
? float:?jiǎn)尉取?/p>
? double:雙精度。
? long double:擴(kuò)展精度。
和整數(shù)類型一樣,每種浮點(diǎn)表示都取決于實(shí)現(xiàn)。本節(jié)不會(huì)詳細(xì)介紹浮點(diǎn)類型,但請(qǐng)注意,這些實(shí)現(xiàn)方式存在大量的細(xì)微差別。在主流桌面操作系統(tǒng)上,float通常有4字節(jié)的精度。double和long double通常有8字節(jié)的精度(雙精度)。
大多數(shù)不參與科學(xué)計(jì)算的用戶可以安全地忽略浮點(diǎn)表示的細(xì)節(jié)。在這種情況下,可以使用double。
注意 對(duì)于那些不能安全地忽略浮點(diǎn)表示細(xì)節(jié)的人來(lái)說(shuō),可以看看與自己硬件平臺(tái)相關(guān)的浮點(diǎn)規(guī)范。浮點(diǎn)存儲(chǔ)和算術(shù)的主要實(shí)現(xiàn)方式在《IEEE浮點(diǎn)算術(shù)標(biāo)準(zhǔn)》(IEEE 754)中有所概述。
1.浮點(diǎn)字面量
浮點(diǎn)字面量默認(rèn)為雙精度。如果需要單精度字面量,則使用f或F后綴;如果需要擴(kuò)展精度字面量,則使用l或L,如下所示:

字面量也可以使用科學(xué)計(jì)數(shù)法:

基數(shù)?和指數(shù)?之間不允許有空格。
2.浮點(diǎn)格式指定符
格式指定符%f顯示帶有小數(shù)位的浮點(diǎn)數(shù),而%e則以科學(xué)計(jì)數(shù)法顯示相同的數(shù)字。我們也可以讓printf使用%g格式指定符,選擇%e或%f中更緊湊的一個(gè)。
對(duì)于double,只需在說(shuō)明符前面加上小寫字母l,而對(duì)于long double,在前面加上大寫字母L。例如,如果想要一個(gè)帶小數(shù)位的double,則可以指定%lf、%le或%lg;對(duì)于long double,則可以指定%Lf、%Le或%Lg。
考慮代碼清單2-3,它探討了打印浮點(diǎn)數(shù)的不同選項(xiàng)。
代碼清單2-3 一個(gè)打印浮點(diǎn)數(shù)的程序

這個(gè)程序聲明了一個(gè)名為an的double?。格式指定符%le?輸出科學(xué)計(jì)數(shù)法結(jié)果6.022141e+23,而%lf?輸出小數(shù)點(diǎn)表示602214090000000006225920.000000。%lg?指定符選擇了科學(xué)計(jì)數(shù)法結(jié)果6.02214e+23。名為hp?的浮點(diǎn)數(shù)(float)使用%e和%f指定符產(chǎn)生類似的printf輸出。但是格式指定符%g決定輸出十進(jìn)制表示9.75而不是科學(xué)計(jì)數(shù)法結(jié)果。
一般來(lái)說(shuō),使用%g來(lái)打印浮點(diǎn)類型。
注意 在實(shí)踐中,可以省略double格式指定符中的l前綴,因?yàn)?b>printf會(huì)將浮點(diǎn)數(shù)參數(shù)提升為雙精度類型。
2.1.3 字符類型
字符類型存儲(chǔ)人類語(yǔ)言信息。這六種字符類型是:
? char:默認(rèn)類型,總是1個(gè)字節(jié)。可能是也可能不是有符號(hào)的(例如:ASCII)。
? char16_t:用于2字節(jié)的字符集(例如:UTF-16)。
? char32_t:用于4字節(jié)的字符集(例如:UTF-32)。
? signed char:與char相同,但保證是有符號(hào)的。
? unsigned char:與char相同,但保證是無(wú)符號(hào)的。
? wchar_t:足夠大以包含實(shí)現(xiàn)平臺(tái)地區(qū)環(huán)境語(yǔ)言設(shè)置中的最大字符(例如:Unicode)。
字符類型char、signed char和unsigned char被稱為窄字符,而char16_t、char32_t和wchar_t由于其相對(duì)的存儲(chǔ)要求,被稱為寬字符。
1.字符字面量
字符字面量是一個(gè)單一的、恒定的字符。所有字符都用單引號(hào)('')括起來(lái)。如果字符是char以外的其他類型,還必須提供一個(gè)前綴:L代表wchar_t,u代表char16_t,而U代表char32_t。例如,'J'聲明一個(gè)char字面量,L'J'聲明一個(gè)wchar_t字面量。
2.轉(zhuǎn)義序列
有些字符不能在屏幕上顯示。相反,它們會(huì)迫使顯示器做一些事情,比如將光標(biāo)移到屏幕的左邊(回車)或?qū)⒐鈽?biāo)向下移動(dòng)一行(換行)。其他字符可以在屏幕上顯示,但它們是C++語(yǔ)法的一部分,如單引號(hào)或雙引號(hào),所以必須非常小心地使用它們。為了將這些字符轉(zhuǎn)換為char,可以使用轉(zhuǎn)義序列,如表2-3中所示。
表2-3 保留字符和它們的轉(zhuǎn)義序列

3.Unicode轉(zhuǎn)義字符
我們可以使用通用字符名(universal character name)來(lái)指定Unicode字符字面量,使用通用字符名的方式有兩種:前綴\u加后面4位的Unicode碼位,或前綴\U加后面8位的Unicode碼位。例如,可以將A字符表示為'\u0041',將啤酒杯字符㊣表示為U'\U0001F37A'。
4.格式指定符
char的printf格式指定符為%c。wchar_t的格式指定符是%lc。代碼清單2-4初始化了兩個(gè)字符字面量x和y,用來(lái)構(gòu)建printf調(diào)用。
代碼清單2-4 一個(gè)為幾個(gè)字符型變量賦值并打印它們的程序

這個(gè)程序輸出Windows binaries start with MZ.。盡管M是窄字符,而Z是寬字符,但printf仍能工作,因?yàn)樵摮绦蚴褂昧苏_的格式指定符。
注意 所有Windows二進(jìn)制文件的前兩個(gè)字節(jié)是字符M和Z,這是對(duì)MS-DOS可執(zhí)行二進(jìn)制文件格式的設(shè)計(jì)者M(jìn)ark Zbikowski的致敬。
2.1.4 布爾類型
布爾類型有兩種狀態(tài):真和假。布爾類型只有一個(gè),即bool。整數(shù)類型和布爾類型可以互相轉(zhuǎn)換:true狀態(tài)轉(zhuǎn)換為1,false狀態(tài)轉(zhuǎn)換為0,任何非零的整數(shù)都轉(zhuǎn)換為true,而0則轉(zhuǎn)換為false。
1.布爾字面量
要初始化布爾類型,需要使用兩個(gè)布爾字面量,即true和false。
2.格式指定符
bool沒(méi)有格式指定符,但我們可以在printf中使用int格式指定符%d來(lái)產(chǎn)生1(代表true)或0(代表false)。原因是printf將任何小于int的整數(shù)值提升為int。代碼清單2-5說(shuō)明了如何聲明布爾變量并檢查其值。
代碼清單2-5 用printf語(yǔ)句打印布爾變量


該程序把b1初始化為true?,b2初始化為false?。然后,把b1和b2打印成整數(shù)(使用%d格式指定符),得到對(duì)應(yīng)b1的1和對(duì)應(yīng)b2的0?。
3.比較運(yùn)算符
運(yùn)算符是對(duì)操作數(shù)進(jìn)行計(jì)算的函數(shù)(詳見7.1節(jié))。操作數(shù)是一種簡(jiǎn)單對(duì)象。關(guān)于使用bool類型的有意義的例子,詳見本節(jié)“比較運(yùn)算符”和“邏輯運(yùn)算符”。
我們可以使用幾個(gè)運(yùn)算符來(lái)構(gòu)建布爾表達(dá)式。回憶一下,比較運(yùn)算符接受兩個(gè)參數(shù)并返回一個(gè)布爾值。可用的運(yùn)算符有相等(==)、不等(!=)、大于(>)、小于(<)、大于或等于(>=)、小于或等于(<=)。
代碼清單2-6顯示了如何使用這些運(yùn)算符來(lái)產(chǎn)生布爾運(yùn)算。
代碼清單2-6 使用比較運(yùn)算符

每次比較都會(huì)產(chǎn)生一個(gè)布爾值結(jié)果?,printf語(yǔ)句將布爾值打印成一個(gè)int結(jié)果?。
4.邏輯運(yùn)算符
邏輯運(yùn)算符在bool類型上處理布爾邏輯。我們可以通過(guò)操作數(shù)的數(shù)量來(lái)對(duì)運(yùn)算符分類。一元運(yùn)算符需要一個(gè)操作數(shù),二元運(yùn)算符需要兩個(gè),三元運(yùn)算符需要三個(gè),以此類推。我們還可以通過(guò)操作數(shù)的類型進(jìn)一步對(duì)運(yùn)算符分類。
取否運(yùn)算符(!)接受一個(gè)操作數(shù),并返回與操作數(shù)相反的結(jié)果。換句話說(shuō),!true產(chǎn)生false,而!false則產(chǎn)生true。
邏輯運(yùn)算符“與”(&&)和“或”(||)是二元的。邏輯“與”(AND)只在兩個(gè)操作數(shù)都為true時(shí)返回true。邏輯“或”(OR)只要有操作數(shù)為true就返回true。
注意 閱讀布爾表達(dá)式時(shí),!的發(fā)音是“not”,如表達(dá)式a&&!b表示“a AND not b”。
邏輯運(yùn)算符一開始可能令人困惑,但它們很快就會(huì)變得直觀。代碼清單2-7展示了邏輯運(yùn)算符。
代碼清單2-7 一個(gè)展示邏輯運(yùn)算符用法的程序

在這里,我們可以看到取否運(yùn)算符?,邏輯“與”運(yùn)算符??,以及邏輯“或”運(yùn)算符??。
2.1.5 std::byte類型
系統(tǒng)程序員有時(shí)會(huì)直接使用原始內(nèi)存,原始內(nèi)存是一個(gè)沒(méi)有類型的位(bit)集合。這種情況下可以使用std::byte類型,它定義在<cstddef>頭文件中。std::byte類型允許按位進(jìn)行邏輯運(yùn)算(見第7章)。使用這種類型而不是整數(shù)類型來(lái)處理原始數(shù)據(jù),常常可以避免難以調(diào)試的編程錯(cuò)誤。
注意,與<cstddef>中的大多數(shù)其他基本類型不同,std::byte在C語(yǔ)言中沒(méi)有確切的對(duì)應(yīng)類型(“C類型”)。像C++一樣,C語(yǔ)言也有char和unsigned char。這些類型使用起來(lái)不太安全,因?yàn)樗鼈冎С衷S多std::byte不支持的運(yùn)算。例如,可以對(duì)char進(jìn)行算術(shù)運(yùn)算,比如加法(+),但不能對(duì)std::byte進(jìn)行該運(yùn)算。這個(gè)看起來(lái)很奇怪的std::前綴被稱為命名空間,詳見8.3.2節(jié)(現(xiàn)在,暫且把命名空間std::當(dāng)作類型名稱的一部分)。
注意 關(guān)于std的發(fā)音,有兩種觀點(diǎn)。一種是把它當(dāng)作“ess-tee-dee”的首字母縮寫,另一種是把它當(dāng)作“stood”的縮寫。當(dāng)提到std命名空間中的類時(shí),說(shuō)話者通常會(huì)暗示命名空間操作符::。因此,可以把std::byte讀作“stood byte”或者“ess-tee-dee colon colon byte”。
2.1.6 size_t類型
size_t類型(也在<cstddef>頭文件中)用來(lái)表示對(duì)象的大小。size_t對(duì)象保證其最大值足以代表所有對(duì)象的最大字節(jié)數(shù)。從技術(shù)上講,這意味著size_t可以占用2個(gè)字節(jié),也可以占用200個(gè)字節(jié),具體取決于實(shí)現(xiàn)方式。在實(shí)踐中,它通常與64位架構(gòu)系統(tǒng)的unsigned long long相同。
注意 size_t是<stddef>頭文件中的一個(gè)C類型,但它與C++的size_t相同,后者位于std命名空間中。偶爾,我們可以看到用(技術(shù)上正確的)std::size_t來(lái)代替。
1.sizeof
一元運(yùn)算符sizeof接受一個(gè)類型并返回該類型的大小(以字節(jié)為單位)。sizeof運(yùn)算符總是返回一個(gè)size_t對(duì)象。例如,sizeof(float)返回存儲(chǔ)float所需的字節(jié)數(shù)。
2.格式指定符
size_t的格式指定符通常是%zd(十進(jìn)制表示)或%zx(十六進(jìn)制表示)。代碼清單2-8顯示了如何檢查某個(gè)系統(tǒng)的幾種整數(shù)類型的大小。
代碼清單2-8 打印幾種整數(shù)類型的字節(jié)數(shù)的程序(輸出來(lái)自Windows 10 x64)

代碼清單2-8分別計(jì)算char?、short?、int?、long?和long long?的大小,并使用%zd格式指定符打印它們的大小。結(jié)果會(huì)因操作系統(tǒng)的不同而不同。從表2-1可以看出,每個(gè)環(huán)境都為整數(shù)類型定義了自己的大小。請(qǐng)?zhí)貏e注意代碼清單2-8中long的返回值;Linux和macOS都定義了8字節(jié)的long類型。
2.1.7 void
void類型表示一個(gè)空的值集合。因?yàn)?b>void對(duì)象不能擁有值,所以C++不允許使用void對(duì)象。我們只在特殊情況下使用void,比如用作不返回任何值的函數(shù)的返回類型。例如,函數(shù)taunt不返回值,因此我們聲明它的返回類型為void:

其他特殊的void用法見第3章。
- Clojure for Domain:specific Languages
- C#程序設(shè)計(jì)教程
- PhoneGap Mobile Application Development Cookbook
- AutoCAD VBA參數(shù)化繪圖程序開發(fā)與實(shí)戰(zhàn)編碼
- Mastering Linux Security and Hardening
- “笨辦法”學(xué)C語(yǔ)言
- ScratchJr趣味編程動(dòng)手玩:讓孩子用編程講故事
- ArcGIS for Desktop Cookbook
- UI設(shè)計(jì)全書(全彩)
- Hands-On Kubernetes on Windows
- Cocos2d-x by Example:Beginner's Guide(Second Edition)
- HTML5+CSS3+JavaScript 從入門到項(xiàng)目實(shí)踐(超值版)
- Android編程權(quán)威指南(第4版)
- 算法超簡(jiǎn)單:趣味游戲帶你輕松入門與實(shí)踐
- 計(jì)算機(jī)程序的構(gòu)造和解釋(JavaScript版)