C 中的陷阱 一

2022-08-29 23:36:42 字數 3110 閱讀 9799

導言

程式語言中充滿陷阱,一不小心就會掉入其中萬劫不復,之所以有陷阱,是因為語言的設計細節不符合程式設計師的直覺

所以你會發現,語言越高階越注重順從程式設計師的直覺。

c++也有許多陷阱,所謂山不過來,我就過去,因此將c++中易錯點、難點集合於此,會不定期更新。

字串與vector

字串字面值與標準庫string不是同一種型別

string s("

hello");

cout

okcout<<"

hello

".size()error

cout<"

world

"okcout<<"

hello

"+"world

"error

strlen、sizeof與size()求字串長度的區別

cout<"

123")返回 3

cout<123")返回 4

string s = "

123"

;cout

返回 3

標準string庫中的getline函式返回時會丟棄換行符

const iterator與const_iterator的區別

vector::const_iterator //

不能改變指向的值,自身的值可以改變

const vector::iterator //

可以改變指向的值,自身的值不能改變

const vector::const_iterator //

自身的值和指向的值都是唯讀的

任何改變vector長度的操作都會使已存在的迭代器失效。如:在呼叫push_back之後,就不能再信賴指向vector的迭代器了

vectorivec;

ivec.push_back(

10);

vector

::iterator it =ivec.begin();

cout

<<*it

cout

<<*it已經失效

陣列與指標

字元陣列除了可以用花括號在定義時初始化外,還可以用字串字面值初始化,但謹記字串字面值包含乙個額外的空字元

char c1 = ;

char c2 = "

hello";

cout

<長度是5

cout<長度是6

乙個陣列不能用另乙個陣列初始化,也不能將乙個陣列賦值給另乙個陣列

int a[3] = ;

int b[3][3] = ,,}; //

right

int c[3][3] = ; //

error

若指標儲存0值,表明它不指向任何物件。但是把int型變數賦值給指標是非法的,儘管此int型變數的值可能為0

int a = 0

;int *p1 = 0; //

right

int *p2 = a; //

error

typedef string *pstring; 

const pstring cstr;

cstr的型別是 string * const 還是 const string * ?

答:是string *const cstr,而非 const string *cstr。容易產生誤解的原因是const限定符既可以放在型別前也可以放在型別後,const pstring cstr等價於pstring const cstr。遇到此類問題時,把const放在型別之後來理解。

區分:int *ip[4] 和 int (*ip)[4]

第乙個表示乙個陣列,元素是int指標

第二個表示乙個指標,指向int陣列,遇到此類問題時,由內向外讀。

運算子

除法/和求模%

若兩個運算元是正數,則除法的結果是正數,求模的結果也是正數

若兩個運算元是負數,則除法的結果是正數,求模的結果是負數

若只有乙個運算元是負數,則除法和求模的結果取決於機器,除法可以確定結果是負數

邏輯與和邏輯或操作符總是先計算其左運算元,然後再計算其右運算元,只有在僅靠左運算元的值無法確定該邏輯表示式的結果時,才會求解其右運算元

區分 if(i

int val = 2

;if(val==true)

多個賦值操作符中,各物件必須具有相同的資料型別,或者具有可轉換為同一型別的資料型別。

int ival; int *pval;

ival = pval = 0; //

error 儘管ival和pval都可以賦值為0

string

s1,s2;

s1 = s2 = "ok"

//ok

如果指標指向不是用new分配的記憶體位址,則在該指標上使用delete是不合法的。

通常編譯器不能斷定乙個指標是否指向動態物件,因此儘管這樣做是錯誤的,但在大部分編譯器上仍能執行通過,但是會產生執行時錯誤。

整形提公升

對於所有比int小的整形(char, signed char, unsigned char, short, unsigned short),如過該型別所有可能值都包含在int中,他們會被提公升為int型,否則,他們將被提公升為unsigned int。

對於包含signed和unsigned int型的表示式,表示式中的signed型整數會被轉換為unsigned型。

int i = -5

;unsigned

int ii = 1

;cout

<<(i>ii)輸出1,非常有趣的結果 原因是int型的i轉換為unsigned int型

short i = -5

;unsigned

short ii = 1

;cout

<<(i>ii)輸出0 比較時short和unsigned short都提公升為int型

C 中的非同步陷阱

c 中的非同步陷阱 原文 有時候,理解一種語言中的缺陷的最好方式是檢視另一種語言如何防止這些缺陷發生。real world functional programming 注 該書已由清華大學出版社引進,中文名 c 與f 程式設計實踐 的作者tomas petricek討論了非同步c 中常見的7項錯誤...

C 中的非同步陷阱

有時候,理解一種語言中的缺陷的最好方式是檢視另一種語言如何防止這些缺陷發生。real world functional programming 注 該書已由清華大學出版社引進,中文名 c 與f 程式設計實踐 的作者tomas petricek討論了非同步c 中常見的7項錯誤,並說明f 如何降低這些缺...

C陷阱與缺陷(一)詞法 陷阱

第一章 詞法 陷阱 1 不同於 1 while c c t c n 賦值運算子 的優先順序低於邏輯運算子 相當於 c t c n 賦給了c,條件永遠為真 2 if x y 應該寫成if x y 0 對變數進行賦值並檢查該變數的新值是否為0 2 和 不同於 和 按位運算子 和 邏輯運算子 和 3 詞法...