You are on page 1of 3

C Traps and Pitfalls / Andrew Koenig

Ch 1 詞法陷阱

● 注意 = 不同於 ==
● & 和 | 不同於 && 和 ||
● 編譯器分解程式的時候傾向於每一個符號包含盡可能最多個字元。因此:
a---b
等於
( a -- ) - b

y=x/*p; /* 代表 y = x / (*p); */;
的 /* 被當成注解的開頭

Ch 2 語法陷阱

● 理解函式宣告
float* g(); // g 為傳回浮點數指標的函式
float (*h)(); // h 為傳回浮點數的函式指標

如果 fp 是一個函數指標,呼叫 fp 指向函數的用法是:
( *fp )();

● 注意運算元的優先權
a < b == c < d;
等於
( a < b ) == ( c < d );

※ 複雜的運算式應使用括號明確標出期望的優先權

● 注意結尾的分號
大部份情形,多餘的分號並不會造成問題,但是在某些情況可能會有預料外的影響:
if ( a > b );
m = a;
無論如何 m = a; 都會執行
缺少分號有時也有不會產生編譯錯誤的情況:
void qoo()
{
if ( n > 3 )
return
foo();
}
如果正好 foo() 傳回值為 void 。以上語法可以通過編譯,卻不是我們想要的。

● 懸掛 else 的問題
else 會與同一對括號內最近未匹配的 if 結合
考慮以下程式碼
if ( x == 0 )
if ( y == 0 ) error();
else
{
z = x + y;
f( &z );
}
實際上代表
if ( x == 0 )
{
C Traps and Pitfalls / Andrew Koenig

if ( y == 0 )
{
error();
}
else
{
z = x + y;
f( &z );
}
}
而程式的本意卻是
if ( x == 0 )
{
if ( y == 0 )
{
error();
}
}
else
{
z = x + y;
f( &z );
}

Ch 3 語意陷阱

● 複製兩個指標並沒有同時複製指標所指向的內容。
● 邊界計算與不對稱邊界
注意欄杆錯誤(差一錯誤)

--n >= 0
等於
n-- > 0
前者會較有效率

if ( bufferPtr == &buffer[N] )
也等於
if ( bufferPtr > &buffer[ N-1 ] )
可以用前者代替後者
雖然 buffer[N] 並不是一個有效的元素,但是 C 語言允許對一個超出陣列邊界的元素取址以及賦值、比較的操
作,但是對此位址指標的解參考動作會發生錯誤。

※ 堅持遵守“不對稱邊界”原則 (考慮 STL 設計)

● 求值順序
C 語言中只有 && 、 || 、 ?: 以及 , 的求值順序有定義。

&&
先對左測求值,需要時才對右側求值
||
先對左測求值,需要時才對右側求值
( a ) ? b : c
先對 a 求值,視結果對 b 或 c 求值
,
先對左側求值,然後丟棄左值,再對右側求值
C Traps and Pitfalls / Andrew Koenig

f( x, y ) 的 x, y 求值順序未定義。
g(( x, y )) 一定是先對 x 求值。

Ch 4 連結

● 宣告與定義
下面的宣告語句如果在所有函式外部,稱為外部變數的定義。
int a;
int a = 7;
上面的語句說明了 a 是一個整數變數,同時為 a 分配了記憶體空間。
下面的宣告語句並不是定義。
extern int a;
上面的語句仍然說明了 a 是一個整數變數,但是 extern 顯示的說明了 a 的記憶體在其他地方中配置。

● 命名衝突與 static 修飾詞


當兩個不同的原始檔都有相同的定義的時候,就會引發命名衝突。static 修飾詞可以用來減少命名衝突。
static 修飾詞宣告的變數或函式的作用域只在定義的原始檔中有效。
static int a;
如果所有的同名變數或函式都是 static 或是只有一個不是 static 就不會有命名衝突的情形。

Ch 5 函式庫

關於函式庫,我們能給出的最好建議是盡量使用系統標頭檔。

Ch 6 前置處理器

● 不能忽視巨集的空格
● 巨集並不是函式
● 巨集並不是敘述句
● 巨集並不是類型定義

Ch 7 可移植性缺陷

Ch 8 建議與答案

● 直接了當表明意圖 (Ch 2)
● 考量最簡單的特例
● 使用不對稱邊界 (Ch 3)
● 注意潛伏在暗處的 Bug
● 防禦性程式編寫

後記

作者給讀者的三個最重要的建議
● 避免使用指針
● 提倡使用程式庫
● 使用類別來表式概念

You might also like