官术网_书友最值得收藏!

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,這樣一下就能明白這個變量保存的是一個人的年齡。

主站蜘蛛池模板: 军事| 平安县| 怀化市| 陇西县| 柏乡县| 昭通市| 天等县| 宜丰县| 仁寿县| 青阳县| 壶关县| 新化县| 长宁区| 门源| 南靖县| 墨玉县| 搜索| 肥西县| 内乡县| 建水县| 九寨沟县| 乌什县| 林州市| 新巴尔虎左旗| 商南县| 修水县| 玉环县| 太谷县| 吉木乃县| 辽阳县| 台北县| 洪洞县| 东安县| 乃东县| 彝良县| 阿勒泰市| 清苑县| 佛坪县| 泰顺县| 阳泉市| 敖汉旗|