如果表示式裡既有帶符號型別又有無符號型別,當帶符號型別取值為負時會出現異常結果。因為帶符號數會自動轉換成無符號數。
unsigned u=10;
int i=-42;
std:
:cout<:
:endl;//輸出-84
std:
:cout<:
:endl;//如果int佔32位,輸出4294967264
引用與指標:
引用並非物件,引用只是為乙個已經存在的物件所起的另外乙個名字。
指標本身就是乙個物件,允許對指標賦值和拷貝,而且在指標的生命週期內它可以先後指向不同的物件。
指標無需再定義時賦初值。但是在塊作用域定義內的指標一定要初始化。
利用相等操作符(==)或!=操作符比較指標時,比較的是兩個指標存放的位址值。
指向指標的引用:
引用本身不是乙個物件,因此不能定義指向引用的指標。但指標是物件,所以存在對指標的引用。
int i=42;
int *p=0;//p是乙個int型指標
int *&r=p;//r是乙個對指標p的引用
r=&i;//令p指向i
*r=0;//令解引用r得到i,i=0;
面對一條比較複雜的指標或引用的宣告語句時,從右到左閱讀有助於弄清楚它的真實含義。
const的引用:
常量引用僅對引用可參與的操作做出了限定,對引用的物件本身是不是乙個常量未作限定。
const的指標:
指向常量的指標不能用於改變其所指物件的值。要想存放常量物件的位址,只能使用指向常量的指標。
const
double pi=3.14;//pi是乙個常量,值不能被改變
double *ptr=π//錯誤,ptr是乙個普通的指標
const
double *cptr=π//指向常量的指標指向乙個常量物件
*ptr=42;//錯誤,不能給*ptr賦值
double dval=3.14;
cptr=&dval;//正確,見note.
note:指向常量的指標沒有規定其所指物件必須是乙個常量。所謂指向常量的指標僅僅要求不能通過該指標改變物件的值,而沒有規定那個物件的值不能通過其他途徑改變。
const指標
常量指標表示指標本身是乙個常量,其必須初始化,而且一旦初始化完成,則它的值,也就是存放在指標中的那個位址就不能再改變。表示為* const,不變的是指標本身的值,而非指向的那個值。
int errnumb=0;
int *const currerr=&errnumb;//currerr一直指向errnumb
const
double pi=3.14159;
const
double *const pip=π//pip是乙個指向常量物件的常量指標
*pip=2.172;//不能通過指標修改物件的值,因指向常量物件
*curerr=0;//可以把curerr指標指向的物件重置,因其指向非常量物件。
頂層const表示指標本身是乙個常量。
底層const表示指標所指物件是乙個常量。
int i=0;
int *const p1=&i;//頂層const
const
int ci=42;//頂層const
const
int *p2=&ci;//底層const
當執行物件的拷貝操作時,常量是頂層const還是底層const區別明顯。
頂層const不受什麼影響。
i=ci;//正確
p2=p3;//正確
當執行物件的拷貝操作時,拷入和拷出物件必須具有相同的底層const資格,或者兩個物件的資料型別必須能夠轉換。
int
*p=p3;//錯誤,p3包含底層const的定義,而p沒有
p2=p3;//正確
p2=&i;//正確,int
*能轉化成const int*
int &r=ci;//錯誤,普通的int&不能繫結到int常量上
const int &r2=i;//正確:const int&可以繫結到普通的int上
constexpr和常量表示式:
常量表示式是值不會改變並且在編譯過程就能得到計算結果的表示式。
我們允許將變數宣告為constexpr型別以便由編譯器來驗證變數的值是否是乙個常量表示式。宣告為constexpr的變數一定是乙個常量,而且必須用常量表示式初始化。
在constexpr宣告中如果定義乙個指標,限定符constexpr僅對指標有效,與指標所指的物件無關。
const
int *p=nullptr;//p是乙個指向整型常量的指標
constexpr
int *q=nullptr;//q是乙個指向整數的常量指標
需要注意的是,const是給定型別的修飾。當使用型別別名的時候,型別別名就是乙個型別。
typedef
char *pstring;//pstring是char*
const pstring cstr=0;//cstr是指向char的常量指標
const pstring *ps;//ps是乙個指標,它的物件是指向char的常量指標
c++11新標準引入了auto型別說明符,用它就能讓編譯器替我們去分析表示式所屬的型別。
(1)推斷引用時,編譯器以引用物件的型別作為auto的型別。
(2)auto 一般會忽略掉頂層const,同時底層const則會保留下來。
(3)如果我們希望推斷出的auto型別是乙個頂層const,需要顯式指出。
decltype型別指示符:選擇並返回運算元的資料型別。
decltype(f()) sum=x;//sum的型別就是函式f的返回型別。編譯器分析表示式並得到它的型別,卻不實際計算表示式的值
如果decltype使用的表示式是乙個變數,則decltype返回該變數的型別(包括頂層const和引用在內)。
const
int ci=0,&cj=ci;
decltype(ci) x=0;//x的型別是const int
decltype(cj) y=x;//y的型別是const int&,y繫結到變數x
decltype(cj) z;//錯誤,z是乙個引用,必須初始化。
如果decltype使用的表示式不是乙個變數,則decltype返回表示式結果對應的型別。
int i=42,*p=&i,&r=i;
decltype(r+0) b;//正確:加法的結果是int,因此b是乙個(未初始化的)int
decltype(*p) c;//錯誤,c是int&,必須初始化。如果表示式的內容是解引用操作,則decltype將得到引用型別。
decltype((variable)) (注意是雙層括號)的結果永遠是引用,而decltype(variable)結果只有當variable本身就是乙個引用時才是引用。
decltype((i)) d;//錯誤:d是int &,必須初始化
decltype(i) e;//正確:e是乙個(未初始化的)int
C primer 變數和基本型別
1.當明知曉數值不可能為負時,選用無符號型別 2.如果數值超過了int的表示範圍,選用long long 3.執行浮點數運算選用double 4.初始化不是賦值,初始化的含義是建立變數時賦予其乙個初始值,而賦值的含義是把物件的當前值擦除,而以乙個新值來替代 5.內建型別的變數未被顯示初始化時,定義於...
C Primer學習筆記2 變數與基本型別
1 整數 字元和布林值的算術型別合稱為整形。2 在windows中回車為 r n liunx中回車為 n mac中回車為 r 3 變數 提供程式可以操作的有名字的儲存區。4 左值 左值可以出現在賦值語句的左邊或者右邊。5 右值 右值只能出現在賦值的右邊,不能出現在賦值語句的左邊。數字字面值是右值 因...
再學C Primer(2) 變數與基本型別
這一章主要介紹了c 中的基本資料型別,還有一些程式設計的技巧。記錄有如下幾點 1.通過增加字尾,能夠強制將字面值整數常量轉換為long或unsigned,unsigned long型別,如 1l long 小數點後加l表示擴充套件精度。2.宣告和定義的區別 定義用於為變數分配儲存空間,還可以為變數指...