第二章 基本內置類型


    頭一章我們已經大致了解了什么是計算機語言,也看了一個小小的C++的入門程序,那么為了更好地學習C++,就讓我們從最基礎的定義開始吧。

    眾所周知,計算機語言除了C++外,還有其他的多種程序語言,比如C,Java,C#,Go,Object-C,甚至是php等腳本語言。這些語言看似各有不同,但實際上卻有着如下一些極其相似的特征:

  •     內置數據類型
  •     變量
  •     表達式和語句
  •     控制結構(if else,while循環等)
  •     函數
  •     注釋

    那么今天我們就從最基礎的基本內置類型開始講起吧。

一 計數方式

    學習前,首先我們需要搞清楚下面幾個問題,即是什么是進制?以及什么又是bit和byte?

1. 二進制與十六進制

(1) 二進制

        所謂二進制,也就是逢二進位的計數方式。這又是什么意思呢?也許有些同學還不太清楚,那么就想想我們平常所使用的數字吧。

        平常我們習慣的的計數方式是十進制,也就是當個位數超過9的時候,就變成了10,即是,個位重新回歸到了0,而十位上則增加了1,再加1的話,則個位繼續增長,直到再次到了9,那么十位上再次加1,變成了20,依次類推,我們便可隨着數字的增加,將位數由十位擴充到百位,千位,萬位等等。

        而二進制也是如此,只不過,當它到2的時候,就需要進位了,數字上就變成了10,如果用十進制表示的話,它就是2,再繼續增加,十進制的3則表示成了二進制的11,十進制的4則變成了二進制的100,十進制的5則是二進制的101等等。

        在C++中為了區分二進制與十進制,則需要在數字前加一個0表示這個數字是一個二進制,比如,0101,這個數字便是與5是等價的(在以后的表達式中,也許可以看到int a = 0101;,這與int a = 5;是一個意思,具體以后再詳細說明)。

(2)十六進制

        十六進制的原理與二進制相同,但是由於它的數字超過了9,那么從10到15又該如何表示呢?很簡單,使用字母a到f即可。而為了區分數字間進制的不同,C++中,十六進制則需要在數字前增加一個0x,這次用20來舉例吧,0x14就是它的十六進制值。

2. bit與byte

    學習了二進制,再來說到bit和byte,也就輕而易舉了。

(1)bit

        bit也就是二進制的位,計算機存儲信息的最小單位。舉個例子,比如十進制的4,也即是二進制的100,一共占用了3個bit。

(2)byte

        byte被稱作字節,通常由8個bit組成,是計算機計算存儲容量的一種計量單位。

二 基本內置類型

1. 算術類型

    C++將整數,浮點數,單個字符和布爾值合稱為算術類型,其存儲空間的大小依機器而定,這里的大小是指用來表示該類型的二進制位(二進制位稱為bit)的數量。C++標准中規定了每個算術類型的最小存儲空間,但是卻並未限定編譯器使用更大的空間。

    

Type

Meaning

Minimum size

bool

Boolean(布爾型)

NA

char

Character(字符型)

8 bits

wchar_t

Wide character(寬字符型)

16 bits

short

Short integer(短整型)

16 bits

int

Integer(整型)

16 bits

long

Long integer(長整型)

32 bits

float

Single-precision floating-point(單精度浮點型)

6 significant digits(有效數字)

double

double-precision floating-point(雙精度浮點型)

10 significant digits(有效數字)

long double

Extended-precision floating-point(擴展精度浮點型)

10 significant digits(有效數字)

                                                                        圖1


    如圖1所示,即是內置算術類型所對應的最小存儲空間,下圖則是我在64位Mac OSX上使用g++編譯器獲得的存儲空間。

Type

Meaning

Minimum size

bool

Boolean

8 bits

char

Character

8 bits

wchar_t

Wide character

32 bits

short

Short integer

16 bits

int

Integer

32 bits

long

Long integer

64 bits

float

Single-precision floating-point

32 bits

double

double-precision floating-point

64bits 

long double

Extended-precision floating-point

128bits

                                                                           圖2

    此外還有long long超長整型,通過sizeof得到的是64bits二進制位。

    注意:

    1. 這些內部關鍵字都為小寫;

    2. 在64位Mac OSX蘋果系統上測試數據,如有不同,請自行用sizeof在其他系統上查看;

    以后將不再專門提起。

(1)整型

    所有整型可分為帶符號(signed)與無符號(unsigned)兩種類型,其中帶符號類型可以表示正數,也可以表示負數(包括0),而無符號型則只能表示大於或等於0的數,如果未寫unsigned,則默認都是帶符號類型,比如unsigned int,表示的是無符號整型。

    那么帶符號數值的正負又是如何區分的呢?如下圖3所示:


signed:

                        圖3

     帶符號數在內存中二進制的首位就是符號位,0代表正數,1代表負數,其中二進制位個數有可能隨編譯器和機器的不同而不同,此文中的位數個數為目前64位機較為普遍的存儲方式。

    A. 短整型

        定義為short,內存中所需的二進制位為16位(注意編譯器與機器的不同),即2個字節,帶符號短整型可表達的數字范圍是從-32768到32767,無符號的范圍則是0到65535。

    下面來看看這是如何計算出來的吧。首先說帶符號短整型,16位二進制,最高位為符號位,則可表示為數字的就只剩下了15位,意思就是說,如果最高位為0,即正數,則數值的最大值就是15位全部為1。

    因為是二進制,15位,每位只能為0或者1,根據排列組合的計算原理,最大值應該為:2的15次方,再減1(215 - 1)。同理,無符號數的最大值為:2的16次方,減1(216 - 1)。

    也許有些同學會不太明白為什么要這么計算,那我們就來簡單地說一下吧。

    比如我們不求15位,我們以簡單的3位來舉例,三個bit位,000,001,010,011,100,101,110,111一共有八種排列的方式,其對應的十進制數分別是0,1,2,3,4,5,6,7,由此,我們可以看出每種排列方式都是獨一無二的,那么我們只要減去全為0的這一種排列方式,得到的就是3位二進制的最大值了。

    這時,也許有同學會問了,三位還好辦,如果位數多了,難道我們也要這么一個個排出來嗎?當然不可能了。上面的方法只不過是為了讓你明白一個簡單的道理罷了,什么道理呢?

    就是我們想要求n位二進制的最大值,只需要求得這n位所有的排列組合的個數,再減去1就是我們所需的結果了。那么又要怎么去求n位的所有的排列組合的個數呢?

    很簡單,再拿三個bit位舉例,首先只看一位,一共就0和1兩種方式,這時,再加上一位,而這一位也只能是0和1兩種,而不論是0還是1,頭一位都只有兩種方式,不過,因為第二位的不同,這時的組合方式就變成了2乘以2,一共4種方式,同理,再加上一位,這一位還是只有0和1兩種方式,不過前面兩位則不管是0還是1都有4種不同的方式,結合這第三位,那么總共就有4乘以2,一共8種方式了。

    現在,大家應該都看明白了吧,總結起來說就是,要得到總的排列組合個數,就是每一位的方式的個數相乘,所得到的乘積就是我們所需要的結果了,在這里,因為方式都是只有0和1兩種,也就是說,n位的排列組合個數等於2的n次方。

    言歸正傳,短整型存儲的位數是16位,如果是帶符號數,最高位作為標志位,則可能出現正0與負0兩種,而負0在這里就是人為地規定為最小值-32768,想要知道詳細信息請看下章關於原碼,反碼和補碼的相關內容。

    B. 整型

      原理同上,就不再多說,定義為int,內存中的二進制位為32位,4個字節,帶符號短整型可表達的數字范圍是從-2147483648到2147483647,無符號的范圍則是0到4294967295。

    C. 長整型

       定義為long,內存中的二進制位為64位,8個字節,帶符號短整型可表達的數字范圍是從-92233720368547758089223372036854775807,無符號的范圍則是0到18446744073709551615

    D. 超長整型

        定義為long long,內存中的二進制位為64位,8個字節,范圍同長整型

(2)字符型

    A. 字符型

        定義為char,內存中二進制位為8位,1個字節,這個字符型基本所有的機器都是如此存儲的。也分為帶符號和無符號兩種。
      B. 寬字符型
        定義為wchar_t,內存中二進制位32位,4字節。

(3)布爾型

      定義為bool,內存中二進制位為8位,1個字節,值為true和false,不過,也可以用其他算術類型的非0表示true,0表示false。

(4)浮點型

     浮點型同整型在內存中的存儲方式有所不同,為了更完整地記錄數據信息,它采用了二進制的科學計數法來存儲數據。那什么是二進制的科學計數法呢?

    為了讓大家更好地理解,我們就先用十進制的科學計數法來解釋一下吧。

    所謂科學計數法,打個比方,735.2,用科學計數法來表示就是7.352 * 10n,即,將一個數字記錄成某個個位數大於0的數字乘以10的n次方的值,這個值與原數字是相等的,這種記數的方法就叫科學計數法。

    而二進制的科學計數法,顧名思義,就是將一個數字記錄成某個個位數大於0的二進制數字乘以2的n次方的值,這個值也必須與原數字相等,用表達式來表示就是:1.xxx * 2n

    為了方便大家理解,用75.25來打個比方,轉換成二進制為1001011.01,用二進制的科學計數法表示出來就是1.00101101 * 26

    這是如何計算出來的呢?

    首先將75.25分成整數部分和小數部分,兩部分分開計算成二進制,先來看看整數部分,要想得到二進制,只需要將75除以2,得到結果為37余1,之后再用37除以2,得到結果18余1,以此類推,直到結果為0,最后將所有的余數按從后往前取,得到的二進制數就是結果,見下圖所示:


                圖4

    75的二進制就是1001011。

    再來提小數部分,0.25,其提取方式與整數部分正好相反,使用乘法,取結果的整數值,最終結果的取值順序按從前往后,如下:

    0.25 * 2 = 0.5    取整數部分0

    0.5 * 2 = 1         取整數部分1

    小數部分的最終結果就是01,加上小數點就是0.01。

    好了,現在小數部分和整數部分都已經有了,整合起來就是1001011.01,表達成二進制科學計數法即是:1.00101101 * 26。也許有些同學還想知道為什么會這么計算呢?其實想想短整型里面提到的原理,逆轉一下思維,就能夠明白其中的道理了。

    說到這里,大家應該都已經明白了二進制的科學計數法,下面就來繼續說說浮點型數據在內存中的存儲方式吧。

    從下圖5我們可以看出,浮點型在內存中主要分為三個部分,其中符號位很好理解,而指數部分,看看上面的1.00101101 * 26,這個6就是指數,它將被存儲在指數位,而0.00101101將被存儲於尾數部分。


                                圖5

  •     符號位
        占1bit,0表示正數,1表示負數。          
  •     指數位   

        用於存儲二進制科學計數法的指數值,因為指數也可以有正負,因此指數位的最高位還是不計算在范圍內,但是它的方式又與符號位不同,它的值是從0到最大值,但是,實際表達的值卻是將它均分成正負。

  •     尾數部分

        用於存儲二進制科學計數法當中的實際數據的小數部分,因為方式都是1.xxx,所有那個小數點前面的1就沒了記錄的必要。另外,浮點型都沒有帶符號與無符號的區別。

    A. 單精度浮點型

        定義為float,內存中占32位,4個字節,數據范圍為-2128~2128,也即是-3.40E38~3.40E38,其存儲方式遵循IEEE754 R32.24標准,其中最高位是符號位,0為正,1為負,指數位占8個bit,尾數部分占23個bit,如下圖6:


                                圖6

        且不提符號位,在這里說說指數位的存儲方式,因為指數也分正負,在這里二進制是從00000000到11111111,如果按照以往的最高位作為符號位的存儲,那么就會有正0與負0的問題,為了更好地將數據按照順序記錄,也就是不會在中途來解決正0和負0的問題,這里就采用了一種移位存儲的方式。

        提到移位存儲,首先我們需要一個基數,這個基數的確定方法就是將最高位設定為0,其余位設定為1,在這里,8位指數的基數就是01111111(127),然后將所需要存儲的數據加上這個基數,那么就可以按照順序唯一表示從-128到127的范圍,而不需要再單獨處理正0和負0的問題了。

    詳細看下圖7:



                                圖7

        以上便是指數部分的存儲了,至於尾數部分,就更簡單了,直接將上面提到的尾數放入即可,不足補零,下面來看一個完整的例子吧。

        還是以75.25(1.00101101 * 26)為例,存儲的數據中,符號位為0,指數位6,存儲為6 + 127 = 133,即是10000101,尾數部分00101101,不足23位,其后補零,如圖8:


                                                                    圖8

        另外,還需要注意一點,尾數部分也決定了精度和有效數字,首先說說精度,比如75.2,其小數部分計算出來就是001100110011......,這數字與實際的十進制所說的數字有部分出入,這就是所說的精度問題。

        而關於有效數字,這尾數部分最大值可為223 -1 = 8388607,一共7位數字,這就是前面提到的有效數字。

    B. 雙精度浮點型

        定義為double,內存中占64位,8個字節,數據范圍為-21024~21024,也即是-1.79E308~1.79E308,遵循IEEE754 R64.53標准,最高位是符號位,0為正,1為負,指數位占11個bit,尾數部分占52個bit,如下圖9:

                                    圖9

        其設計原理與單精度浮點型相同,不同的是存儲的長度不同,這導致了數據范圍的不同,還有基數也變為了0111111111(1023),有效數字增大到252 -1 = 4503599627370495,一共16位數字。

    C. 擴展精度浮點型

        定義為long double,內存中占64位,8個字節,同雙精度浮點型。

2. void空類型

    void類型沒有對應的值,是一種特殊的類型,通常用做無返回值函數,以及通用的指針使用,在此不做詳談,等以后接觸到的時候,再提及。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com