2.1 C語言基本數據類型
“程序=數據結構+算法”,算法很容易理解,就是解決問題的思路和步驟,那數據結構是什么呢?一個程序中肯定要用到數據,而數據有簡單的,也有復雜的,如何對這些數據進行設計和定義,如何進行數據的存儲和訪問,這些數據間有著什么樣的關系,這些都是數據結構要考慮的事情。可見,數據對于一個程序是非常重要的。C語言里有不少數據類型,按照先易后難的原則,本節主要講述C語言中的基本數據類型。
C語言的基本數據類型有三類:整型、實型與字符型。
2.1.1 整型
整型,顧名思義,整數類型,也就是不帶小數點的數值類型。是不是太簡單了?不過整型按占用內存大小和所能表示的數值范圍又可分為短整型、標準整型、長整型和長長整型,分別用關鍵字“short int”“int”“long int”“long long int”表示。為什么要分成這么多的類型呢?想要理解這個問題,必須先了解一下內存存儲相關的問題,因為這里涉及了內存大小,所以下面簡單介紹一下二進制、位和字節的相關知識。
1.二進制、位和字節
我們的日常生活中離不開數字,但生活中通常所使用的都是十進制的數,而計算機只能處理二進制數,所以要把十進制數轉換成相對應的二進制數,計算機才能處理。
十進制的規則是逢十進一,它的每一位都是由0~9的數字構成。對應的二進制的規則就是逢二進一,它的每一位只能由0或1構成。此外,在C語言中除了二進制,還有可能會用到八進制和十六進制。所以對于“10”,如果它是十進制數,就是10;如果它是二進制的話,那么它所對應的十進制數就是2;若是八進制,對應的十進制數就是8;若是十六進制,則其對應的十進制數就是16。下面列出十進制數0~15所對應的二進制、八進制和十六進制數值。

對于十進制整數23,轉換成對應的二進制碼為10111,二進制碼里的每個“0”或“1”稱為一個二進制位(Bit),簡稱位。在兩個位中左為高位,右為低位。
內存的最小存儲單位為字節(Byte),1字節有8位(即1字節可以存放8個二進制的“0”或“1”),所以要把整數“23”存放在內存中至少需要1字節的空間,位數不夠8時前面補0。即十進制數“23”對應的8位二進制碼為“0001 0111”,如圖2.1所示。

圖2.1 存儲在1字節內存中的十進制數“23”
在這8位中,位序為7的位是最高位,位序為0的位是最低位,其中最高位是作“正負”的標記位來使用的,稱為符號位,即符號位的位值為“0”表示正數,為“1”表示負數,剩余的7位用于存儲整數所對應的二進制碼,稱為數據位。所以1字節所能表示的取值范圍從–128(二進制碼為“1000 0000”)~127(二進制碼為“0111 1111”),共256個。
要想把一個更小或更大的整數存儲到內存中,8位就顯然無能為力了,必須使用更多的內存空間,例如2字節就擁有16位,可表示的取值范圍變成從–32768(二進制碼為“1000 0000 0000 0000”)~32767(二進制碼為“0111 1111 1111 1111”),共65536個,擴大了256倍。
大家可以想象一下,如果C語言中只有一種整數類型的話,讓其使用多少字節的內存比較合適呢?假如使用的內存字節數多,則能表示的數值范圍大,但如果用它來存放一些小數值,就會造成內存的浪費;反之,如果使用的內存字節少,可能又存放不了比較大的數值,無論怎樣都不能兩全其美。
現在明白為什么把整型分為這么多的類型了吧,根據不同的數值大小,使用不同大小字節的內存空間,既不浪費內存空間,又能放得下相應的數值,真正做到“物盡其用”。表2.1是本書的開發環境下各種整型的內存大小和所能表示的取值范圍。
表2.1 整型的內存大小和取值范圍

一個整型“搖身一變”成了四種類型,是不是挺有趣?其實它還可以再變出四種類型。這次新變出的四種新類型和之前的四種非常類似。
2.無符號整型
前面講到把一個整數轉換成對應的二進制碼,其中的最高位是用來標記正負數的符號位。這時會不會有讀者突發奇想:“那如果不要這個符號位,把它也變成數據位,用于存放整數的二進制位,不是就能多出1倍的取值范圍嗎?”不得不佩服大家的聰明,也很有想象力,但不夠準確。
如果沒有了表示正負整數的符號位,那么就沒有了負數的表現能力,所存儲的全部視為正整數。最終的結果就是正整數的取值范圍擴大了一倍,但總的取值范圍沒變。例如1字節所能表示的取值范圍從0(二進制碼為“0000 0000”)至255(二進制碼為“1111 1111”),還是256個;2個字節的取值范圍從0(二進制碼為“0000 0000 0000 0000”)至65535(二進制碼為“1111 1111 1111 1111”),還是65536個。
對于這種沒有符號位,全是數據位的整數類型,我們稱之為無符號整型,它的關鍵字為“unsigned”。之前所講的四種整數類型都是有符號整型,它們也有個關鍵字“signed”,不過通常不用寫,也就是默認的整型就是有符號的,若想使用無符號的整型,前面加上“unsigned”關鍵字即可。在本書的開發環境下,各種無符號整型的內存大小和取值范圍如表2.2所示。
表2.2 無符號整型的內存大小和取值范圍

2.1.2 實型
整數類型講完應該講小數類型了。C語言把這種帶小數點的數值類型稱為實型或浮點數類型。雖然實型與整型只有一字之差,但它卻有和整型完全不同的內存存儲方式,通過上一節的學習,我們知道了有符號整型的最高位是符號位,其他的都是數據位,對于無符號整型來講,全部都是數據位。而實型卻是分為三段進行存儲的:符號位、階碼位、數據位。其中最高位是符號位,中間部分是階碼位(或稱指數位),最后部分是數據位(或稱尾數位),如圖2.2所示。

圖2.2 實型內存存儲示意圖
這種類似于科學計數法的內存存儲方式,能夠輕松存儲一個比較大的數值,并擁有非常大的取值范圍,但是在數值的精度上可能會有所損失,畢竟魚與熊掌不可兼得。由于實型的這種特殊的內存存儲方式,導致在處理速度上沒有整型的快,所以如果程序中不涉及小數的話,盡量還是選用整型。
實型按照內存大小分為單精度浮點數類型、雙精度浮點數類型和長雙精度浮點數類型,關鍵字分別為“float”“double”和“long double”。其中單精度浮點數類型,內存大小為4個字節,即32位(符號位1位,階碼位8位,數據位23位);雙精度浮點數類型的內存大小為8字節,即64位(符號位1位,階碼位11位,數據位52位);長雙精度浮點數類型是相對較新的一種實型,它擁有更大的數值表現和存儲能力,但由于C標準并未對它的內存大小有所規定,所以在不同的系統和編譯器上,可能被實現為各種不同字節大小的版本。實型的內存大小和取值范圍如表2.3所示。
表2.3 實型的內存大小和取值范圍

2.1.3 字符型
也許讀者會有疑問,為什么沒有1字節大小的整型呢?其實是有的,只不過通常我們把它稱為字符型,關鍵字為char。也就是說,字符型就是1字節的整型。那為什么要把它稱為字符型呢?為了能夠在程序中使用字符,最初C語言規定將1字節的整型作為字符來使用,更確切地說,是將0~127這128個正整數作為字符使用,這就是大名鼎鼎的ASCII碼(美國信息交換標準代碼)。
ASCII碼中定義的全是英文字符,例如大寫和小寫的英文字母、數字字符、標點符號以及特殊的控制字符。例如用整數10表示換行字符,整數32表示空格字符,整數48~57表示數字字符0~9,整數65~90表示大寫字母A~Z,整數97~122表示小寫字母a~z等等。這里需要注意的是數字字符“0”和整數0是不同的概念。數字字符“0”對應的整數是48,而整數0也有一個對應的英文字符,它是空字符,通常用它來表示一個字符串的結束。ASCII碼中的其他的一些常用字符見表2.4。
表2.4 ASCII常用字符與整數對照表

既然字符型就是1字節的整型,我們完全可以把字符型當成整型來使用。字符型是不是也分有符號和無符號呢?答案是肯定的。默認的字符型就是有符號的,取值范圍為–128~127。ASCII碼就采用里面的正數部分,若在字符型的前面加上“unsigned”關鍵字,那么就是無符號的字符類型了,其取值范圍為0~255,具體見表2.5。
表2.5 字符型內存大小和取值范圍

2.1.4 設置類型別名
在C語言中,允許使用“typedef”關鍵字來設置類型別名。所謂設置類型別名,就是給數據類型起一個新的名字。設置類型別名的格式為:
typedef 原類型名 新類型名;
設置類型別名之后,新類型名具有與原類型名相同的數據類型,用戶可以隨意選擇使用新類型名和原類型名,效果是一樣的。既然一樣,那設置類型別名有什么好處呢?
1.簡化長類型名
C語言中,有些數據類型的名字比較長,很容易造成書寫錯誤。若給這樣的數據類型設置一個簡短的別名,就能減少書寫上的錯誤。例如:
typedef unsigned int uint;
通過typedef給unsigned int類型設置一個簡短的別名uint,后面代碼中需要使用unsigned int的地方,可以使用uint,是不是方便多了,類型名的字符少了,書寫錯誤自然也會減少。
2.便于代碼維護
例如我們給short類型設置一個別名“DATATYPE”,并在代碼中都使用這個別名:
typedef short DATATYPE;
過了一段時間后,發現short類型太小,不夠用,想換成更大的類型int,那么只需改動設置類型別名的地方:
typedef int DATATYPE;
現在代碼中所有的DATATYPE都表示為int類型了。是不是很方便?若是沒有設置類型別名,就得到代碼中一一查找要修改的地方,對代碼量大的程序來說工作量很大。
3.擴展類型信息
舉個例子,在保存某人的基本信息的代碼中,如果看到一個int類型的變量,怎么能知道這個變量所表示的是什么呢?是人的身高、體重還是年齡?這時可以給int類型設置類型別名:
typedef int Age;
在代碼中,變量的類型使用Age,這樣一下就能明白這個變量保存的是一個人的年齡。
- Advanced Splunk
- Hands-On Enterprise Automation with Python.
- 運用后端技術處理業務邏輯(藍橋杯軟件大賽培訓教材-Java方向)
- Linux C編程:一站式學習
- Python項目實戰從入門到精通
- Oracle GoldenGate 12c Implementer's Guide
- Julia 1.0 Programming Complete Reference Guide
- Python程序設計開發寶典
- Emotional Intelligence for IT Professionals
- Oracle 12c從入門到精通(視頻教學超值版)
- Docker:容器與容器云(第2版)
- INSTANT LESS CSS Preprocessor How-to
- Android項目實戰:博學谷
- GO語言編程從入門到實踐
- Implementing NetScaler VPX?(Second Edition)