詞法分析中的“貪心法”
- 每個符號應(yīng)該包含盡可能多的字符轴咱。
a---b
等同于(a--)-b
。
a+++++b
被編譯器視為((a++)++)+b
烈涮,語法上是不正確的朴肺。
字符與字符串
單引號引起的字符代表一個整數(shù)。
雙引號引起的字符串代表一個指向無名數(shù)組起始字符的指針坚洽。
理解函數(shù)聲明
(* (void (*) () ) 0) ();
這是一個經(jīng)典的例子戈稿。分析如下:
void (*) ()
指向返回值為void類型的函數(shù)指針( void (*) () ) 0
將0進行類型轉(zhuǎn)換(* ( void (*) () ) 0) ();
調(diào)用地址為0的子例程
運算符優(yōu)先級
- 優(yōu)先級由高到低排列
- 數(shù)組下標(biāo)** [ ]、函數(shù)調(diào)用操作符( )讶舰、各結(jié)構(gòu)成員選擇操作符 ->**和 **. **鞍盗。自左與右結(jié)合。
- 單目運算操作符跳昼,包括類型轉(zhuǎn)換般甲。 自右至左結(jié)合。
- 雙目運算操作符鹅颊,其中優(yōu)先級順序 算術(shù)運算符>位移運算符>關(guān)系運算符>邏輯運算符欣除。 自左向右結(jié)合
- 三目運算符(條件運算符)。 自右至左結(jié)合挪略。
- 賦值運算符历帚。 自右至左結(jié)合滔岳。
- 逗號運算符。 自左與右結(jié)合挽牢。
運算符優(yōu)先級所引發(fā)的錯誤很難發(fā)現(xiàn)谱煤。
while ( c == '\t '|| c = ' '|| c == '\n' )
事實上,該語句的正確劃分如下禽拔。
while ( (c == '\t '|| c ) = ( ' '|| c == '\n' ))
該語句不僅是將==誤寫為=刘离,還導(dǎo)致了表達式左端為不可修改的左值。
switch函數(shù)的優(yōu)勢與劣勢
- 程序在switch中順序執(zhí)行睹栖,不受case標(biāo)號影響硫惕。
switch (color) {
case 1:printf("red");
case 2:printf("yellow");
case 3:printf("blue");
}
若color=2
執(zhí)行結(jié)果為 yellowblue
使用不對稱邊界
- 用第一個入節(jié)點和第一個出界點來表示一個數(shù)值的范圍
一個字符串中由下標(biāo)為16到下標(biāo)為37的字符元素所組成的字串,它的長度是多少呢野来?
若將其表示為整數(shù)x滿足x** >= 16(入界點)且x < **38(出界點)恼除,則很容易計算其結(jié)果。
該技巧可以用在for循環(huán)中曼氛,用來循環(huán)結(jié)束的標(biāo)志豁辉。
使用頭文件
- 每個外部對象只在一個頭文件中聲明,需要用到該外部對象的所有模塊都包含這個頭文件(包括其定義該外部對象的模塊)
返回整數(shù)的getchar函數(shù)
- 單引號引起的字符代表一個整數(shù)舀患。
- 若使用char接收徽级,可能無法容下EOF。
宏可能產(chǎn)生的問題
- 宏定義中的空格
#define f (x) ((x)-1)
該宏定義為f代表(x) ((x)-1)
- 宏不是函數(shù)
#define abs(x) x>0?x:-x
abs(a-b)
展開后為
a-b>0?a-b:-a-b //并不是我們期望的-(a-b)
因此聊浅,宏定義中應(yīng)該把每個參數(shù)都用括號括起來餐抢,整個表達式也應(yīng)該用括號括起來。
- 存在副作用
#define max(a,b) ( (a) > (b) ? (a) : (b) )
biggest = max ( biggest , x[i++])
展開后
biggest = ( (biggest)>(x[i++]) ? (biggest) : (x[i++])
i一次可能遞增2低匙。
- 宏不是類型定義
#define T1 struct foo *
T1 a,b
展開為
struct foo * a , b
兩者類型不同旷痕。