介紹語言的基本知識和標準庫
第二章 變數和基本類型
一些語言,如Smalltalk和Python等,在程式運行時檢查資料類型;與之相反,C++是一種待用資料類型語言,它的類型檢查發生在編譯時間。
- 內建類型(built-in type):由語言定義的類型,如int。
- 類類型(class type):程式員自訂的資料類型。
++資料類型告訴我嘛資料的意義以及我們能在資料上執行的操作。++
基本內建類型
術語chunk(塊):用於處理儲存,使儲存具有結構的最基本方法。塊的位元一般是2的冪,這樣可以一次處理8、16、32、64或者128位。注意區分block。
++可定址的最小記憶體塊稱為“位元組(byte)”;儲存的基本單元稱為“字(word)”,通常由幾個位元組組成。++
- 算數類型(arithmetic type):整數、浮點數、單個字元、布爾值
- 整型(integral type):表示整數、字元和布爾值的算術類型合稱為整型
- 字元型:char(單個機器位元組:byte)和wchar_t(寬字元型,用於擴充字元集,比如漢字和日語)
- short:半個機器字長;int:一個機器字長;long:兩個機器字長。ps:在32位機器中int和long的字長通常是相等的。最小儲存空間分別為16位、16位和32位
- 整型的賦值:賦值時,取該值對該類型取值數目求模後的值。
- 浮點型:單精確度、雙精確度、擴充精度(long double)
- 一般而言,float佔1個字(32位元),double佔2個字(64位元),long double以3或4個字(96或128位元)來表示。
- 通常選用double,float的精度損失大(double能至少保證10位有效數字,float只能保證6位),而double的計算代價相對於float可以忽略。
- 16位signed最大數32767,unsigned最大數65535。
- 空類型(void):通常用作無傳回值函數的傳回型別
類型轉換
unsigned char c = -1; //假設char佔8位元,c的值為255signed char c2 = 256; //假設char佔8位元,c2的值是未定義的
當我們賦給無符號類型一個超出它表示範圍的值時,結果是初始值對無符號類型表示數值總數模數後的餘數。
當我們賦給帶符號類型一個超出它表示範圍的值時,結果是未定義的(undefined)。此時,程式可能繼續工作、可能崩潰,也可能產生垃圾資料。
不可混用帶符號類型和無符號類型。如果運算式裡這兩種類型都有,帶符號數會自動轉換為無符號數。
字面值常量(literal constant)
稱之為字面值是因為只能用它的值稱呼他,稱之為常量是因為它的值不能夠修改。
只有內建類型存在字面值,沒有類類型的字面值,因此也沒有標準庫類型的字面值。
使用十進位、八進位(0開頭)或十六進位(0x或0X開頭)
//20的三種表示:20 /*十進位*/024 /*八進位*/0x14 /*十六進位*/
整型字面值:字面值常量類型預設為int或long型。通過加尾碼能夠強制將字面值轉化為long、unsinged、unsigned long,尾碼為L、U、UL或LU(小寫亦可。不提倡使用l,易與1混淆)。
浮點字面值:十進位或科學計數法來表示(用e或者E)。預設double類型,加F或f表示單精確度,加L或l表示擴充精度。
布爾字面值:true和false。
字元字面值:
名稱 |
書寫 |
分行符號 |
\n |
水平定位字元 |
\t |
縱向定位字元 |
\v |
退格符 |
\b |
斷行符號符 |
\r |
疑問號 |
\? |
雙引號 |
\” |
字串字面值:
雙引號括起來的0個或多個字元。
為了相容C語言,C++所有的字串字面值都由編譯器自動在末尾添加一個Null 字元(‘\0’),因此,其實際長度要比它的內容多1。
寬字元字面值:在字串前面加L,如L“asdff”。
多行字面值:兩個字串字面值位置緊鄰且僅由空格、縮排和分行符號分割,則它們實際上是一個整體。
不依賴未定義行為和機器相關行為,否則這樣的程式時不可移植的(nonportable)。
指標字面值:nullptr
變數
變數提供了程式可操作的有名字的儲存區
- 左值和右值
- 左值(lvalue):變數的地址,或者是一個代表“ 對象在記憶體中的位置”的運算式。
- 右值(rvalue):變數的值
變數名出現在賦值運算子的左邊,就是一個左值;而出現在賦值運算子右邊的變數名或字面常量就是一個右值。 如: val1=val2/8 這裡的val1是個左值,而val2和8都是右值。
- 對象:記憶體中具有類型的地區
- 變數名:即變數的標識符(identifier)。
1. 由字母、數字和底線組成.
2. 變數名必須以字母或底線開頭,並且區分大小寫。(函數體外的變數名不能以底線開頭)
3. C++關鍵字不能用做標識符
4. 不能包含兩個連續的底線
5. 不能以底線開頭後緊跟一個大寫字母
定義對象(如:int a;)
每個定義都是以類型說明符(type specifier)開始的(如:int)
int ival(1024);//direct-initialization,直接初始化int ival = 1024;//copy-initialization,複製初始化//註:直接初始化文法更靈活,且效率更高。
列表初始化(list initialization)(C++11新特性)
int ival{1024};int ival = {1024};long double ld = 3.1415926536;int a{ld}, b = {ld}; //錯誤:轉換未執行,因為存在丟失資訊的風險int c(ld), d = ld; //正確:轉換執行,且丟失部分值
初始化&賦值:初始化不是賦值。
預設初始化(default initialized):如果內建類型的變數未被顯示初始化,它的值由定義的位置決定。定義於任何函數體之外的變數被初始化為0,內部的將不被初始化。
建議初始化每個內建型變數,以保證程式安全。
初始化
變數的聲明
extern int i; //聲明i而非定義iint j; //定義j
變數名的範圍(scope):以花括弧分隔
全域範圍(global scope)
塊範圍(block scope)
複合類型(compound type)
引用(reference),此處指左值引用(lvalue reference)。
int ival = 1024;int &refVal = ival; //refVal指向ival(是ival的另一個名字)int &refVal; //報錯,引用必須被初始化
指標(pointer)
int i = 42; int &r = i; //&緊隨類名出現,因此是聲明的一部分,r是一個引用int *p; //*緊隨類名出現,因此是聲明的一部分,p是一個指標p = &i; //&出現在運算式中,是一個取地址符*p = i; //*出現在運算式中,是一個解引用符int &r2 = *p;
指標是對象,允許賦值和拷貝,且在指標的生命週期內它可以先後指向不同的幾個對象。
指標無需在定義時賦值。
指標類型和它所指向的對象的類型必須匹配。
int *ip1, *ip2;int val = 4;int *p = &val;
如果指標指向了一個對象,則允許用解引用符(操作符*)來訪問該對象:
int ival - 42;int *p = &ival;cout << *p; //由符號*得到指標p所指的對象,輸出42*p = 0; //由符號*得到指標p所指的對象,即可經由p為變數ival賦值cout << *p; //輸出0
符號的含義由上下文決定
null 指標
int *p1 = nullptr;int *p2 = 0;int *p3 = NULL; //需要首先#include cstdlib
const限定符
定義常量。
- 指標和const
- 頂層const(top-level const):表示指標本身是個常量
- 底層const(low-level condt):表示指標所指的對象是個常量
指向常量的指標(pointer to const)
const double pi = 3.14;double *ptr = π //錯誤!const double *cptr = π //正確*cptr = 42; //錯誤!cptr指向常量,不能向常量賦值double dval = 3.14;cptr = &dval; //正確,但不能通過cptr改變dval的值,因為cptr以為自己指向的是常量
常量指標(const pointer)
int errNum = 0;int *const curErr = &errBum; //curErr將一直指向errNumconst double pi = 3.14;const double *const pip = π //pip是一個指向常量對象的常量指標
constexpr和常量運算式
C++11新標準:將變數聲明為constexpr類型以便由編譯器來驗證變數的值是否是一個常量運算式。(用const,有些常量的具體值直到運行時才能擷取)
在constexpr聲明中如果定義了一個指標,限定符僅對指標有效,與指標所知的對象無關。也就是說它把所定義的對象置為頂層const。
const int *p = nullptr; //p是一個指向常量的普通指標constexpr int *q= nullptr; //q是一個常量指標constexpr int i = 42;constexpr const *p = &i;
處理類型
類型別名(type alias)
typedef
typedef double wages; //wages是double的同義字
typedef wages base, *p; //base是double的同義字,p是double*的同義字
別名聲明(alias declaration)
using S1 = Sales_item; //S1是Sales_item的同義字
auto類型說明符
decltype類型指示符
const int ci = 0, &cj = ci; decltype(ci) x = 0; //x的類型是const intdecltype(cj) y = x; //y的類型是const int&,y綁定到變數xdecltype(cj) z; //錯誤:z是一個引用,必須初始化
int i = 42, *p = &i, &r = i;decltype(r + 0) b; //正確:加法的結果是int,因此b是一個未初始化的intdecltype(*p) c; //錯誤:c是int&,必須初始化
自訂資料結構
標頭檔通常包含哪些只能被定義一次的實體,如類、const和constexpr變數等。
前置處理器(preprocessor):如#include,當前置處理器看到#include標記時就會用指定的標頭檔內容替代#include。
標頭檔保護符(header guard):有效防止重複包含發生
#ifndef SALES_DATA_H#define SALES_DATA_H#include <string>struct Sales_data { ... //此處省略};#endif
參考:C++Primer第五版
介紹語言的基本知識和標準庫
相關文章:
第一章C++:函數傳回值、GNU編譯器命令
第三章C++:字串string、向量vector和數組