1.詞法分析中的「貪心法」
c語言中的某些符號,例如/、*、和=,只有乙個字元長,稱為單字元符號。而c語言中的其他一些符號,例如/*和==,包括了多個字元,稱為多字元符號。當c編譯器讀入乙個字元'/'後又跟了乙個字元'*',那麼編譯器就必須做出判斷:是將其作為兩個分別的符號對待,還是合起來作為乙個符號對待。c語言解決這個問題的方法可以歸納為乙個很簡單的規則:每乙個符號應該包含盡可能多的字元。也就是說,編譯器將程式分解成符號的方法是:從左到右乙個字元乙個字元地讀入,如果該字元可能組成乙個符號,那麼再讀入下乙個字元,判斷已經讀入的兩個字元組成的字串是否可能是乙個符號的組成部分;如果可能,繼續讀入下乙個字元,重複上述判斷,直到讀入的字元組成的字串已不再可能組成乙個有意義的符號。例如:a---b與表示式a -- - b的含義相同,而與a - -- b 的含義不同。 y = x/*p中的."/*"表示注釋的開始,而不是除以*p。
2.理解函式宣告
例子:解釋 (*(void(*)())0)(); 這個語句的含義。
雖然上面的這個語句比較複雜,但是其實構造這類表示式其實只有一條簡單的規則:按照使用的方式來宣告。任何c變數的宣告都由兩部分組成:型別以及一組類似表示式的宣告符。例如,宣告乙個int型變數a,int a;一旦我們知道了如何宣告乙個給定型別的變數,那麼該型別的型別轉換符就很容易得到:只需要把宣告中的變數名和宣告末尾的分號去掉,再將剩餘的部分用乙個括號整個「封裝」起來即可。例如:float (*h)();表示h是乙個指向返回值為浮點型別的指標,因此(float (*)())表示乙個「指向返回值為浮點型別的函式的指標的」型別轉換符。此時,(*(void(*)())0)(); 也就不難理解了,(void(*)())0表示將0強制轉化為(void(*)())型別,然後是'*'的解引用,然後是函式呼叫。可以使用typedef使得上面的例子更簡潔,typedef void (*funcptr)(); 那麼 (*(void(*)())0)();可表示為(*(funcptr)0)();
3.變數的定義與宣告要保證型別一致
如果在乙個原始檔中定義了char filename = "/etc/passwd";而在另外乙個檔案中宣告了extern char* filename;儘管在乙個語句中引用filename的值將得到指向該陣列起始元素的指標,但是filename的型別是「字元陣列」,而不是「字元指標」。在第二個宣告中,filename被確定為乙個指標。這兩個隊filename宣告使用儲存空間的方式是不同的,它們無法以一種合乎情理的方式共存。字元陣列filename的記憶體布局如圖1所示,字元指標filename的記憶體布局如圖2所示。
圖1 字元陣列filename的記憶體布局示意圖
圖2 字元指標filename的記憶體布局示意圖
4.返回整數的getchar函式
考慮下面的函式:
main()
此函式想表達的功能是讀入乙個字元並把它輸出,直到沒有輸入時(在vc6.0中為ctrl+d鍵)返回eof,但是由於這裡的c被宣告為char型,而不是int型,可能會導致幾種問題。
1)某些合法的輸入字元在被「截斷」後使得c的取值與eof相同,這會導致程式在檔案複製的中途終止;
2)c根本不可能取到eof這個值,這會導致程式陷入死迴圈;
3)有時候還有可能出現這種情況,getchar的返回結果在賦給char型別的變數c時發生「截斷」操作,但是用來和eof比較的確是getchar函式的返回值,即沒有進行截斷的那個值;
C陷阱和缺陷 中的幾個知識點
1.詞法分析中的 貪心法 c語言中的某些符號,例如 和 只有乙個字元長,稱為單字元符號。而c語言中的其他一些符號,例如 和 包括了多個字元,稱為多字元符號。當c編譯器讀入乙個字元 後又跟了乙個字元 那麼編譯器就必須做出判斷 是將其作為兩個分別的符號對待,還是合起來作為乙個符號對待。c語言解決這個問題...
C 的幾個知識點
1 陣列的氣泡排序 int nums new int int temp 0 for int j 0 j nums.length 1 j for int i 0 i nums.length i console.readkey 2 反轉語句 array.reverse nums for int i le...
c 中的知識點
1.類和結構的區別 1.從儲存上,類儲存在堆上的引用,結構是儲存在棧上的值型別 2.從關鍵字上,類使用class,結構使用struct 3.繼承上,類可以繼承,結構不可以繼承 4.類是引用型別,結構是值型別 2ref和out區別 ref無論是按值傳遞還是按照引用傳遞,任何變數都要初始化 out變數不...