C++編程:基本數據類型

尚硅谷教育 發佈 2023-05-25T04:29:44.087914+00:00

定義變量時,不可或缺的一個要素就是數據類型。本質上講,這就是為了實現計算需求,我們必須先定義好數據的樣式,告訴計算機這些數據占多大空間,這就是所謂「數據類型」的含義。C++支持豐富的數據類型,它內置了一套基本數據類型,也為我們提供了自定義類型的機制。

定義變量時,不可或缺的一個要素就是數據類型。本質上講,這就是為了實現計算需求,我們必須先定義好數據的樣式,告訴計算機這些數據占多大空間,這就是所謂「數據類型」的含義。

C++支持豐富的數據類型,它內置了一套基本數據類型,也為我們提供了自定義類型的機制。

接下來我們先介紹基本數據類型,主要包括算術類型和空類型(void)。其中算術類型又包含了整型和浮點型;而空類型不對應具體的值,只用在一些特定的場合,比如一個函數如果不返回任何值,我們可以讓void作為它的返回類型。

1. 整型

整型(integral type)本質上來講就是表示整數的類型。

我們知道在計算機中,所有數據都是以二進位「0」「1」來表示的,每個叫做一位(bit);計算機可尋址的內存最小單元是8位,也就是一個字節(Byte)。所以我們要訪問的數據,都是保存在內存的一個個字節里的。

一個字節能表示的最大數是28 = 256,這對於很多應用來講顯然是不夠的。不同的需求可能要表示的數的範圍也不一樣,所以C++中定義了多個整數類型,它們的區別就在於每種類型占據的內存空間大小不同。

C++定義的基本整型包括char、short、int、long,和C++ 11新增的long long類型,此外特殊的布爾類型bool本質上也是整型。

在C++中對它們占據的長度定義比較靈活,這樣不同的計算機平台就可以有自己的實現了(這跟C是一樣的)。由於char和bool相對特殊,我們先介紹其它四種。C++標準中對它們有最小長度的要求,比如:

l short類型至少為16位(2位元組)

l int至少2位元組,而且不能比short短

l long至少4位元組,而且不能比int短

l long long至少8位元組,而且不能比long短

現在一般系統中,short和long都選擇最小長度,也就是short為16位、long為32位、long long為64位;而int則有不同選擇。我們一般使用的電腦作業系統,比如Windows 7、Windows 10、Mac OS等等的實現中,int都是32位的。

所以short能表示的數有216 = 65536 個,考慮正負,能表示的範圍就是-32768 ~ 32767;而int表示的數範圍則為 - 231 ~ 231 - 1。(大概是正負20億,足夠用了)

#include<iostream>

using namespace std;

int main()

{

short a = 1;

cout << "a = " << a << endl;

cout << "a的長度為:" << sizeof(a) << endl;

int b;

cout << "b的長度為:" << sizeof(b) << endl;

long c;

cout << "c的長度為:" << sizeof(c) << endl;

long long d;

cout << "d的長度為:" << sizeof(d) << endl;

cin.get();

}

這裡我們用到了sizeof,這是一個運算符,可以返回某個變量占用的字節數。我們可以看到,變量占用的空間大小隻跟類型有關,跟變量具體的值無關。

2.無符號整型

整型默認是可正可負的,如果我們只想表示正數和0,那麼所能表示的範圍就又會增大一倍。以16位的short為例,本來表示的範圍是-32768 ~ 32767,如果不考慮負數,那麼就可以表示0 ~ 65535。C++中,short、int、long、long long都有各自的「無符號」版本的類型,只要定義時在類型前加上unsigned就可以。

short a = 32768;

cout << "a = " << a << endl;

cout << "a的長度為:" << sizeof a << endl;

unsigned short a2 = 32768;

cout << "a2 = " << a2 << endl;

cout << "a2的長度為:" << sizeof a2 << endl;

上面的代碼可以測試無符號數表示的範圍。需要注意,當數值超出了整型能表示的範圍,程序本身並不會報錯,而是會讓數值回到能表示的最小值;這種情況叫做「數據溢出」(或者「算術溢出」),寫程序時一定要避免。

由於類型太多,在實際應用中使用整型可以只考慮三個原則:

  • 一般的整數計算,全部用int;
  • 如果數值超過了int的表示範圍,用long long;
  • 確定數值不可能為負,用無符號類型(比如統計人數、銷售額等);

3. char類型

如果我們只需要處理很小的整數,也可以用另外一種特殊的整型類型——char,它通常只占一個字節(8位)。不過char類型一般並不用在整數計算,它更重要的用途是表示字符(character)。

計算機底層的數據都是二進位位表示的,這用來表示一個整數當然沒有問題,可怎麼表示字母呢?這就需要將常用的字母、以及一些特殊符號對應到一個個的數字上,然後保存下來,這就是「編碼」的過程 。

最常用的字符編碼集就是ASCII碼,它用0~127表示了128個字符,這包括了所有的大小寫字母、數字、標點符號、特殊符號以及一些計算機的控制符。比如字母「A」的編碼是65,數字字符「0」的編碼是48。

在程序中如果使用char類型的變量,我們會發現,列印出來就是一個字符;而它的底層是一個整數,也可以做整數計算。

char ch = 65;

cout << "65對應的字符為:" << ch << endl;

char ch2 = ch + 1;

cout << "66對應的字符為:" << ch2 << endl;

char類型用來表示整數時,到底是有符號還是無符號呢?之前的所有整型,默認都是有符號的,而char並沒有默認類型,而是需要C++編譯器根據需要自己決定。

所以把char當做小整數時,有兩種顯式的定義方式:signed char 和 unsigned char;至於char定義出來的到底帶不帶符號,就看編譯器的具體實現了。

另外, C++還對字符類型進行了「擴容」,提供了一種「寬字符」類型wchar_t。wchar_t會在底層對應另一種整型(比如short或者int),具體占幾個字節要看系統中的實現。

wchar_t會隨著具體實現而變化,不夠穩定;所以在C++11新標準中,還為Unicode字符集提供了專門的擴展字符類型:char16_t和char32_t,分別長16位和32位。

4. bool類型

在程序中,往往需要針對某個條件做判斷,結果只有兩種:「成立」和「不成立」;如果用邏輯語言來描述,就是「真」和「假」。真值判斷是二元的,所以在C語言中,可以很簡單地用「1」表示「真」,「0」表示「假」。

C++支持C語言中的這種定義,同時為了讓代碼更容易理解,引入了一種新的數據類型——布爾類型bool。bool類型只有兩個取值:true和false,這樣就可以非常明確地表示邏輯真假了。bool類型通常占用8位(1個字節)。

bool bl = true;

cout << "bl = " << bl << endl;

cout << "bool類型長度為:" << sizeof bl << endl;

我們可以看到,true和false可以直接賦值給bool類型的變量,列印輸出的時候,true就是1,false就是0,這跟C語言裡的表示其實是一樣的。

5. 浮點類型

跟整數對應,浮點數用來表示小數,主要有單精度float和雙精度double兩種類型,double的長度不會小於float。通常,float會占用4個字節(32位),而double會占用8個字節(64位)。此外,C++還提供了一種擴展的高精度類型long double,一般會占12或16個字節。

除了一般的小數,在C++中,還提供了另外一種浮點數的表示法,那就是科學計數法,也叫作「E表示法」。比如:5.98E24表示5.98×1024;9.11e-31表示9.11×10-31。

// 浮點類型

float f = 3.14;

double pi = 5.2e-3;

cout << "f = " << f << endl;

cout << "pi = " << pi << endl;

這就極大地擴展了我們能表示的數的範圍。一般來講,float至少有6位有效數字,double至少有15位有效數字。所以浮點類型不僅能表示小數,還可以表示(絕對值)非常大的整數。

(float和double具體能表示的範圍,可以查找float.h這個頭文件)

6. 字面值常量

我們在給一個變量賦值的時候,會直接寫一個整數或者小數,這個數據就是顯式定義的常量值,叫做「字面值常量」。每個字面值常量也需要計算機進行保存和處理,所以也都是有數據類型的。字面值的寫法形式和具體值,就決定了它的類型。

(1)整型字面值

整型字面值就是我們直接寫的一個整數,比如30。這是一個十進位數。而計算機底層是二進位的,所以還支持我們把一個數寫成八進位和十六進位的形式。以0開頭的整數表示八進位數;以0x或者0X開頭的代表十六進位數。例如:

  • 30 十進位數
  • 036 八進位數
  • 0x1E 十六進位數

這幾個數本質上都是十進位的30,在計算機底層都是一樣的。

在C++中,一個整型字面值,默認就是int類型,前提是數值在int能表示的範圍內。如果超出int範圍,那麼就需要選擇能夠表示這個數的、長度最小的那個類型。

具體來說,對於十進位整型字面值,如果int不夠那麼選擇long;還不夠,就選擇long long(不考慮無符號類型);而八進位和十六進位字面值,則會優先用無符號類型unsigned int,不夠的話再選擇long,之後依次是unsigned long、long long和unsigned long long。

這看起來非常複雜,很容易出現莫名其妙的錯誤。所以一般我們在定義整型字面值時,會給它加上一個後綴,明確地告訴計算機這個字面值是什麼類型。

  • 默認什麼都不加,是int類型;
  • l或者L,表示long類型;
  • ll或者LL,表示long long類型;
  • u或者U,表示unsigned無符號類型;

我們一般會用大寫L,避免跟數字1混淆;而u可以和L或LL組合使用。例如9527uLL就表示這個數是unsigned long long類型。

(2)浮點型字面值

前面已經提到,可以用一般的小數或者科學計數法表示的數,來給浮點類型賦值,這樣的數就都是「浮點型字面值」。浮點型字面值默認的類型是double。如果我們希望明確指定類型,也可以加上相應的後綴:

  • f或者F,表示float類型
  • l或者L,表示long double類型

這裡因為本身數值是小數或者科學計數法表示,所以L不會跟long類型混淆。

(3)字符和字符串字面值

字符就是我們所說的字母、單個數字或者符號,字面值用單引號引起來表示。字符字面值默認的類型就是char,底層存儲也是整型。

而多個字符組合在一起,就構成了「字符串」。字符串字面值是一串字符,用雙引號引起來表示。

  • 『 A 』 字符字面值
  • 「Hello World!」 字符串字面值

字符串是字符的組合,所以字符串字面值的類型,本質上是char類型構成的「數組」(array)。關於數組的介紹,我們會在後面章節詳細展開。

Ø 轉義字符

有一類比較特殊的字符字面值,我們是不能直接使用的。在ASCII碼中我們看到,除去字母、數字外還有很多符號,其中有一些本身在C++語法中有特殊的用途,比如單引號和雙引號;另外還有一些控制字符。如果我們想要使用它們,就需要進行「轉義」,這就是「轉義字符」。

C++中規定的轉義字符有:

其中,經常用到的就是符號中的問號、雙引號、單引號、反斜線,還有換行符和制表符。

// 轉義字符

char tchar = '\n';

cout << "tchar = " << tchar << endl;

cout << "Hello World!\t\"Hello C++!\"" << endl;

(4)布爾字面值

布爾字面值非常簡單,只有兩個:true和false。

7. 類型轉換

我們在使用字面值常量給變量賦值時會有一個問題,如果常量的值超出了變量類型能表示的範圍,或者把一個浮點數賦值給整型變量,會發生什麼?

這時程序會進行自動類型轉換。也就是說,程序會自動將一個常量值,轉換成變量的數據類型,然後賦值給變量。

// 1. 整數值賦給bool類型

bool b = 25; // b值為true,列印為1

// 2. bool類型賦值給算術整型

short s = false; // s值為0

// 3. 浮點數賦給整數類型

int i = 3.14; // i值為3

// 4. 整數值賦給浮點類型

float f = 10; // f值為10.0,列印為10

// 5. 賦值超出整型範圍

unsigned short us = 65536; // us值為0

s = 32768; // s值為-32768

轉換規則可以總結如下:

  • 非布爾類型的算術值賦給布爾類型,初始值為0則結果為 false , 否則結果為true ;
  • 布爾值賦給非布爾類型,初始值為 false 則結果為0,初始值為 true 則結果為1;
  • 浮點數賦給整數類型,只保留浮點數中的整數部分,會帶來精度丟失;
  • 整數值賦給浮點類型,小數部分記為0。如果保存整數需要的空間超過了浮點類型的容量,可能會有精度丟失。
  • 給無符號類型賦值,如果超出它表示範圍,結果是初始值對無符號類型能表示的數值總數取模後的餘數。
  • 給有符號類型賦值,如果超出它表示範圍,結果是未定義的( undefined )。此時,程序可能繼續工作,也可能崩潰。

C++中的數據類型轉換,是一個比較複雜的話題。我們這裡先了解一下變量賦值時的自動類型轉換,關於更加複雜的轉換,我們會在下一章繼續介紹。

關鍵字: