掌握細節並不難,難的是如何運用之妙!
詞:單詞
符號=作為賦值運算,是因為操作頻繁,書寫簡單
a—b與表示式a – - b的含義相同,而與a - – b的含義不同
y = x/*p與y = x / *p不同(第乙個/*被理解為注釋符)
理解:這也許就是編碼規範要求操作符兩側新增合理空格的原因之一吧
用雙引號引起的字串,代表的卻是乙個指向無名陣列起始字元的指標。
字元』\0』對應的十進位制是0
括號(),陣列下標,函式呼叫,結構成員選擇操作符->/. > 單目運算子 > 算數運算子 > 移位運算子 > 關係運算子 > 邏輯運算子 > 賦值運算子 > 條件運算子(三目運算子)
*p++,先計算p++
while (c=getc(in) != eof)和while ((c=getc(in)) != eof)
case語句結束時不加break的場景,最好加上注釋// fall-through
練習題:
為什麼c語言允許初始化列表**現多餘的逗號,如:
int a = ;
enum ;
據說是為了簡化**生成工具的邏輯處理。
c語言中的陣列值得注意的地方有以下兩點:
c語言中只有一維陣列,而且陣列的大小必須在編譯期就作為乙個常數確定下來。然而,c語言中陣列的元素可以是任何型別的物件,當然也可以是另外乙個陣列。這樣,要「**」出乙個多維陣列就不是一件難事。
(備註:c99標準允許變長陣列(vla))
對於乙個陣列,我們只能夠做兩件事:確定該陣列的大小,以及獲得指向該陣列下標為0的元素的指標。其他有關陣列的操作,哪怕它們乍看上去是以陣列下標進行運算的,實際上都是通過指標進行的。換句話說,任何乙個陣列下標運算都等同於乙個對應的指標運算,因此我們完全可以依據指標行為定義陣列下標的行為。
「欄杆錯誤」,也常被稱為」差一錯誤「(off-by-one error)
問題:100英呎長的圍欄每隔10英呎需要一根支撐用的欄杆,一共需要多少根欄杆?
解決方法:用第乙個入界點和第乙個出界點來表示乙個數值範圍,即[a, b)
如:x>=16且x<=37,表示成:x>=16且x<38
這個問題,還會出現在:佇列,棧等緩衝區操作中
#define n 1024
static char buffer[n];
static char *bufptr;
bufptr = buffer;
……if (bufptr == &buffer[n])
c語言中只有四個運算子(&&、||、?: 和,)存在規定的求值順序。
運算子&&和||首先對左側運算元求值,只在需要時才對右側運算元求值
運算子?:有三個運算元:在a?b:c中,運算元a首先被求值,根據a的值再求運算元b或c的值
逗號運算子,首先對左側運算元求值,然後該值被」丟棄「,再對右側運算元求值。
」溢位「,是指有符號整數算術運算中發生的現象
#define f (x) ((x)-1)
#define f(x) ((x)-1)
#define max(a,b) ((a)>(b) ? (a) : (b)),每個引數用括號括起來,整個結果表示式也用括號括起來
max(a++, b),引數不能出現***,a會被計算兩次
避免巨集展開成龐大的表示式,如:max(a,max(b,max(c,d)))
assert巨集
#define assert(e) if (!e) assert_error(__file__, __line__)
例子:
if (x > 0 && y > 0)
assert(x > y);
else
assert(y > x);
展開後:
if (x > 0 && y > 0)
if (!(x > y)) assert_error("foo.c", 37);
else
if (!(y > x)) assert_error("foo.c", 39);
問題:出現了if和else重新組隊。
#define assert(e)
展開後:
if (x > 0 && y > 0)
;else
;
問題:else之前的分號是乙個語法錯誤
#define assert(e) ((void)((e) || assert_error(__file__, __line__)))
展開後:
if (x > 0 && y > 0)
((void)((x > y)) || assert_error("foo.c", 37)));
else
((void)((y > x)) || assert_error("foo.c", 39)));
理解:
if, else**塊加{},所以**規範一般要求,即便只有一條語句的**塊也要加{}
根據巨集具體作用定義形式,有的需要定義成表示式,有的需要定義成語句塊(用do while(0)包裹巨集內容)
#define t1 struct foo *
typedef struct foo * t2;
t1 a, b; // 擴充套件為:struct foo * a, b; 乙個是指標變數,乙個是結構體變數
t2 a, b;
C陷阱與缺陷 筆記
這本書很薄,看目錄感覺講的也很基礎,估計能較快看完。算是開始閱讀前陣子買的那波書的熱身吧。學過編譯原理,我們應當了解,編譯器的工作基本過程。在詞法分析中,不同編譯器的不同設定,會帶來不同的問題。雖然很是細微,但是如果出錯,可能編譯器不提示,讓人抓狂.int a 0195 int b 0215 int...
C陷阱與缺陷 筆記
fortan formula translator 公式翻譯程式語言 fibonacci 斐波那契 為什麼n 的含義是n 0,而不是n 0?a b的含義是?賦值操作符為什麼是 而不是 ascii碼 貪心原則?10是否能表示成010?單引號括起來的乙個字元表示乙個整數,雙引號括起來的乙個字元代表乙個指...
C陷阱與缺陷筆記
第一章 詞法陷阱 1.1 不同於 1.2 與 不同於 與 1.3 詞法分析中的 貪心法 1.4 整型變數 1.5 字元與字串 第二章 語法陷阱 2.1 理解函式宣告 2.2 運算子的優先順序問題 2.3 注意作為語句結束標誌的分號 2.4 switch語句 2.5 函式呼叫 2.6 懸掛 else引...