第2章 變數和基本類型
⒉⒈ 基本內建類型
⒈ 算數類型(arithmetic types):表示數值(即整數和浮點數)的類型
⒉⒈⒈ 整型
⒈ 整型(Integral Types):表示整數、字元和布爾值的算數類型。包括:
⑴ char: 字元型,通常單個機器位元組,最小8位
wchar_t:
寬字元型,最小16位
用於擴充字元集,如漢字和日語
⑵ short:
短整型,通常半個字長,最小16位
由於範圍較小容易越界,執行整型算數運算時很少使用
int:
整型,通常1個字長,最小16位,大多數機器使用32位表示
用於整型運算時不易出錯
long:
長整型,通常1或2個機器字長,最小32位
對用32位表示 int 而用64位表示
long 的機器,後者代價遠高於前者,使用時如何選擇應視情況而定
⑶ bool:
布爾型,賦值時0值算數類型為 false, 其餘為
true
⒉ 帶符號(signed)和無符號(unsigned)類型
⑴ 帶符號類型可以表示正數、0和負數; 無符號只能表示非負數
⑵ int,short,long 都預設為
signed
⑶ char 有3種不同類型: 普通,
unsigned,
signed, 但只有2種表示方式
char 使用哪一種表示方式由編譯器決定
⒊ 整型值的表示
⑴ unsigned 型中,所有位都用來表示數值
⑵ signed 型如何用位由編譯器決定。常見策略為使用其中一個位作符號位,該位為1則值為負,為0則值為0或正
⒋ 將一個越界值賦給一個指定類型的變數時:
⑴ 若類型為 unsigned, 編譯器通過對越界值模數來滿足要求
⑵ 若類型為 signed, 行為未定義
⒉⒈⒉ 浮點型
⑴ float:
單精確度浮點數,一般一個字長,最小6位有效數字
其可能的精度損失不可忽視
⑵ double:
雙精確度浮點數,一般兩個字長,最小10位有效數字
其計算代最小8位價與 float 相當,使用它基本不會錯
⑶ long
double:
擴充精度浮點數,一般三或四個字長,最小10位有效數字
其提供的額外精度往往無必要,且需承擔額外的運行代價
⒉⒉ 字面值常量
⒈ 整數字面值
⑴ 定義字面值整型常量可以使用十進位、八進位(以0開頭表示)和十六進位(以0x或0X開頭表示)中的任意一種
⑵ 預設為 int 或
long 型(值適合 int 就為
int 型,比
int 大最小8位就為
long 型)
⑶ 數值後加上尾碼 U, L, UL 分別表示 unsigned,
long,
unsigned long
⒉ 浮點數字面值
⑴ 可以使用普通的十進位標記法或科學計數法表示。使用後者時,用E或e來標示指數
⑵ 預設為 double 型
⑶ 數值後加上尾碼 F, L 分別表示 float,
long double
⒊ 布爾字面值: true, false
⒋ 字元字面值
⑴ 通過用單引號引起的字元或逸出字元定義
⑵ 前面加上L表示wchar_t型
⑶ C++中定義的逸出字元有:
/’ 單引號
/” 雙引號
// 反斜線
/0 Null 字元
/a 響鈴
/b 後退
/f 走紙
/n 換行
/r 斷行符號
/t 水平定位字元
/v 垂直定位字元
/oct 編號為oct的字元(oct表示一個八位元,不必以0開頭)
/xhex 編號為hex的字元(hex表示一個十六進位數,不以0x或0X開頭)
⒌ 字串字面值
⑴ 通過用雙引號引起的若干個字元或逸出字元定義
⑵ 類型為以 NULL 結束的 const
char 型數組(結尾的Null 字元由編譯器自動添加)
⑶ 前面加上L表示寬字元串面值
⑷ 兩個相鄰的僅由空格、定位字元或分行符號分開的(寬)字串面值,可串連成一個新(寬)字串字面值
這一特性可用於處理長字串字面值
試圖串連一個字串字面值和一個寬字元串字面值將導致未定義行為
⑸ C++代碼中,在一行末尾加反斜線符號(其後不可再出現空格或注釋)可將該行與下一行當作同一行處理(因此第二行可能不允許有正常的縮排)
這一特性也可用於處理長字串字面值,但並不常用
⒉⒊ 變數
⒈ 左值(lvalue)和右值(rvalue)
⑴ 左值:可以出現在賦值操作的左邊或右邊的值。非 const 左值可讀可寫。
⑵ 右值:可以出現在賦值操作右邊但不能出現在左邊的值。可讀不可寫。
變數是左值
⒉ 變數名,可由字母或底線開頭,用字母、數字和底線組成;大小寫敏感
⒊ 變數的定義
⑴ 變數的定義為變數分配儲存空間,還能同時指定其初始值。在程式中,一個變數有且僅有一個定義
⑵ 變數的初始化
① 提供初始化式時,支援兩種初始化形式:
a. 複製初始化:用等號(=) (注:不是賦值)
b. 直接初始化:將初始化式放在括弧中;更靈活,效率更高
對內建類型而言,二者幾乎沒有差別;對類類型而言,有時必須用後者
② 不提供初始化式:
a. 對內建類型變數:在函數體外定義的自動初始化為0,在函數體內定義的不進行自動初始化
b. 對類類型變數:若該類提供預設建構函式則調用它,否則必須提供顯式初始化式
③ 同時定義多個變數時,以上各種初始化形式(包括不提供初始化式)都可混用;可以用同一定義中前面已定義變數的值給後面的變數初始化
⑶ 在變數首次使用處定義變數往往能增加代碼可讀性,減少開銷
⒋ 變數的聲明
⑴ 變數的聲明向程式表明變數的類型和名字。聲明可以在程式中出現多次。定義也是聲明
⑵ 使用 extern 關鍵字可聲明一個變數而不定義它,常用於使資料橫跨多個檔案的範圍
⑶ 若聲明有初始化式,則被當作定義,即使使用了 extern 關鍵字也一樣
⑷ 在全域範圍中定義的非 const 對象在整個程式的各個檔案中都可見,只要在其它檔案中聲明它就可以訪問;
但全域範圍中的 const 對象預設為其定義所在檔案的局部對象,只有在定義前指定它為
extern 才能在其它檔案中訪問
⒉⒊⒍ 名字的範圍
⒈ 範圍(scope):程式的一部分,名字在其中有意義。
C++中的範圍有以下幾種:
⑴ 全域:名字定義在任何其他範圍外
⑵ 類:名字由類定義
⑶ 命名空間:名字在命名空間中定義
⑷ 局部:名字在函數中定義
⑸ 塊:名字定義在語句塊中(即定義在一對花括弧裡)
⑹ 語句:名字在語句(如 if 、
while 、 for 語句)的條件內定義
⒉ 範圍可嵌套,外層範圍的名字在內層可見。內層範圍中的名字可以屏蔽(hide)外層中同樣的
⒉⒌ 引用
⒈ 引用(reference)是一種複合類型(即用其它類型定義的類型),表示另一個(非引用)對象的別名,對它的所有操作都直接作用在該對象上
引用主要用作函數形參
⒉ 引用定義格式為
類型名& 標識符
( 數組的引用定義格式: 類型名 (&標識符)[維度]
指標的引用定義格式: 類型名*& 標識符 )
同時定義多個引用時每個引用的標識符前都要加&(以及[維度]和*)
定義引用必須用對應類型的對象初始化,表示綁定到該對象,且一經綁定不可更改
⒊ const 引用是唯讀,可以綁定到不同但相互關聯類型的對象,也可綁定到右值;
非 const 對象只能綁定到與該引用同類型的對象
⒉⒍ 定義類型名
⒈ typedef 用於定義一個類型的同義字。定義格式為:
typedef 類型 標識符;
⒉ 常為以下3種目的使用 typedef :
⑴ 隱藏特定類型實現,強調使用類型的目的
⑵ 精簡類型定義以便理解
⑶ 多次使用同一類型,保持每次使用目的明確
⒉⒎ 枚舉
⒈ 枚舉(enumeration)類型由一組枚舉成員(enumerator)組成
其中每個枚舉成員都有自己的名字,初始化為整型 const 值(值可重複,但初始化後不能修改)
⒉ 定義格式: enum 枚舉類型名 {用逗號分開的枚舉成員列表};
可以用常量運算式通過賦值操作符為列表中某些枚舉成員提供初始值,未提供初值的預設每個值比前一個大1(第一個預設為0)
⒊ 每個 enum 都唯一定義一種類型,枚舉類型的對象初始化或賦值時只能通過該類型的枚舉成員或另一對象進行
⒉⒐ 標頭檔
⒈ 因為標頭檔包含在多個源檔案中,故一般只應包含對象和函數的聲明而不包含定義,但以下除外:
⑴ 類
⑵ 用常量運算式初始化的 const 對象
(若不是用常量運算式初始化,則應和其它對象一樣在一個檔案中定義並初始化,並在標頭檔中添加 extern 聲明以便多檔案分享權限設定)
⑶ inline 函數
以上都可以在多個檔案中定義(只要定義一致)。需要在標頭檔定義是因為編譯器需要它們的定義來產生代碼
⒉ 前置處理器
⑴ #include 只接受一個標頭檔名作為參數
標頭檔名在角括弧中被認為是標準標頭檔,編譯器將在預定義位置尋找
標頭檔名在引號中被認為是非系統標頭檔,通常在源檔案所在位置尋找
⑵ 可使用前置處理器定義標頭檔保護符(header guard)避免多重包含,如:
#ifndef XXX_HEADER_H
#define XXX_HEADER_H
// 標頭檔內容,包括類等的定義
#endif