《從陷阱中學習C/C++》讀書筆記

OpenSoucre發表於2013-11-30

1、運算子優先順序很容易引起問題,如a = 4<<1+1,由於<<的優先順序低於+,故其執行過程為 a = 4<<(1+1);

常見的運算子優先關係:(具體參照部落格

優先順序

運算子

名稱或含義

使用形式

結合方向

說明

1

[]

陣列下標

陣列名[常量表示式]

左到右

--

()

圓括號

(表示式)/函式名(形參表)

--

.

成員選擇(物件)

物件.成員名

--

->

成員選擇(指標)

物件指標->成員名

--

 

2

-

負號運算子

-表示式

右到左

單目運算子

~

按位取反運算子

~表示式

++

自增運算子

++變數名/變數名++

--

自減運算子

--變數名/變數名--

*

取值運算子

*指標變數

&

取地址運算子

&變數名

!

邏輯非運算子

!表示式

(型別)

強制型別轉換

(資料型別)表示式

--

sizeof

長度運算子

sizeof(表示式)

--

 

3

/

表示式/表示式

左到右

雙目運算子

*

表示式*表示式

%

餘數(取模)

整型表示式%整型表示式

4

+

表示式+表示式

左到右

雙目運算子

-

表示式-表示式

5

<< 

左移

變數<<表示式

左到右

雙目運算子

>> 

右移

變數>>表示式

 

6

大於

表示式>表示式

左到右

雙目運算子

>=

大於等於

表示式>=表示式

小於

表示式<表示式

<=

小於等於

表示式<=表示式

7

==

等於

表示式==表示式

左到右

雙目運算子

=

不等於

表示式!= 表示式

 

8

&

按位與

表示式&表示式

左到右

雙目運算子

9

^

按位異或

表示式^表示式

左到右

雙目運算子

10

|

按位或

表示式|表示式

左到右

雙目運算子

11

&&

邏輯與

表示式&&表示式

左到右

雙目運算子

12

||

邏輯或

表示式||表示式

左到右

雙目運算子

 

13

?:

條件運算子

表示式1?

表示式2: 表示式3

右到左

三目運算子

 

14

=

賦值運算子

變數=表示式

右到左

--

/=

除後賦值

變數/=表示式

--

*=

乘後賦值

變數*=表示式

--

%=

取模後賦值

變數%=表示式

--

+=

加後賦值

變數+=表示式

--

-=

減後賦值

變數-=表示式

--

<<=

左移後賦值

變數<<=表示式

--

>>=

右移後賦值

變數>>=表示式

--

&=

按位與後賦值

變數&=表示式

--

^=

按位異或後賦值

變數^=表示式

--

|=

按位或後賦值

變數|=表示式

--

 

15

逗號運算子

表示式,表示式,…

左到右

--

 

2、c++巨集定義時要對每個變數和語句加上括號,在編譯之前,將巨集帶入語句看有沒有邏輯錯誤,

  在c++中使用巨集定義的函式儘量使用行內函數代替;

  使用巨集來儲存常量的儘量使用const變數代替;

  使用巨集來縮短長變數名的,可以用引用來代替;

3、給巨集定義命名時,要避免巨集名稱與系統庫的定義同名。

4、將char轉換為int時,一定要注意char的最高位是0還是1,一般系統中char為為有符號的,在將char轉換為int時,先將char轉換為unsigned char

char a = 0x9A;
int util = (int)(unsigned char)a;

  將int轉換為char時,如果系統預設char為unsigned char,則下面會出現問題:

char c;
while((c = getchar())!=EOF){  //如果char是unsigned char則EOF(-1)會轉換為(unsigned char)255
    putchar(c);  
}

解決方法是

int c; //去除int轉換為char的強制轉化
while((c = getchar())!=EOF){  
    putchar(c);  
}

對於變數的強制轉換,需要注意型別的截斷和擴充套件。

一定要注意有符號int和無符號int比較的後果:

#include <iostream>
#include <vector>
using namespace std;

int main(){
    vector<int> a;
    a.push_back(1);
    a.push_back(2);
    int i = -1;
    if(i< a.size()) cout<<"True"<<endl; ////由於size()返回的是size_t,其是unsigned int此時i會轉換成unsigned int, 
    else cout<<"False"<<endl;
    return 0;
}

在位域結構體中,注意結構體變數型別

#include <iostream>
#include <vector>
using namespace std;

struct data{
    int flag : 1;    //注意這代表符號位,取值範圍為0或-1
    int other: 31;
};
int status(){
    return 1;
}

int main(){
    struct data test;
    test.flag = 1;  //返回值1賦給flag時會出現溢位,
    cout<<test.flag;
}

解決方法是將結構體中的變數變成unsigned int

5、浮點數比較時,一般比較他們的差值在一定範圍內

6、關於常量指標和指標常量:

  int *const px ;  //指真本身是常量,它指向的地址是不可改變的,但地址裡的內容可以通過指標改變。

  const int *py;  // 指標指向的是常量,它不能指向變數,它指向的內容不能改變,不能通過指標來修改它指向的內容,但指標本身不是常量,它自身的值可以改變。

 7、關鍵字extern可以置於變數和函式前,以表示變數或者函式的定義在別的檔案中,提示編譯器遇到此變數或函式時在其他模組中尋找定義。

 8、對結構體進行賦值時,建議具體到結構體的成員變數名。

struct rectangle
{
    int length;
   int width;    
}

struct rectangle  rect  ={rect.length = 4, rect.width = 2};

 9.關於cin>>和getline混用導致的奇怪問題

#include <iostream>
#include <vector>
using namespace std;

int  main(){
    int num;
    string str;
    cin >> str;    //讀取到連續的字串後,立即停止,使用者按下Enter鍵時,"\n"留在輸入流中
    cin.ignore(); //解決方法用cin.ignore()清除留在輸入流中的換行符
    getline(cin,str); //getline遇到換行符結束
    cout<<num << " "<<str<<endl;
}

 

 

相關文章