c專家編程閱讀筆記

1.警惕不同類型數據的隱式轉換,儘量不使用unsigned類型。char short bitfield enum 在表達式中會自動轉換爲int,float自動轉換爲double,函數參數也是表達式,所以當參數傳遞給函數時也會發生類型轉換。如果編譯器能保證運算結果一致,也可以省略類型提升,常出現在表達式中存在常量操作數的時候。老式的編譯器僅僅支持int double 指針三種參數類型,爲了簡化參數傳遞,所以常會發生參數類型轉換。而ansi c標準支持多種類型參數,而且參數類型相同時不會發生類型轉換。

2.對優先級和結合型不確定時,使用括號明確表示。

3.使用typedef 簡化類型聲明。對於複雜聲明,從標識符開始逐層解釋。

4.定義分配存儲空間,而聲明只是表明名稱和類型,定義時特殊的聲明。編譯器爲每個變量分配一個地址(左值),並將變量名與地址放入符號表中,該地址在編譯時可知,而變量中的值(右值),只有在運行時才知道。

5.數組和指針是不同的,一個直接訪問一個間接訪問,指針變量值的訪問多了一次取地址的操作。一個文件中定義全局變量char c[10]; 另一文件中聲明extern char *c;是錯誤的。因爲聲明瞭c爲字符指針,即會按照指針的方式去訪問,首先從符號表中得到指針變量的地址,然後取出指針變量值(也就是所指向字符變量的地址)進行訪問,而c定義爲字符數組,取出的值實際爲第一個字符,以此作爲地址訪問就出現錯誤。同樣,若定義全局變量char *p;另一文件中聲明extern char p[];進行訪問也會出錯。

6.靜態鏈接:庫函數包含在可執行文件中;動態鏈接:庫函數在運行時被加載到內存,可執行文件中存有鏈接庫的路徑名和文件名。動態鏈接可以避免函數庫或操作系統版本更新時重新鏈接程序,而且可以減小可執行文件大小,節省磁盤和內存,因其可爲多個進程共享。

7.動態庫名字爲libname.so,通過編譯時使用-lname 選項告訴編譯器連接到libname.so。編譯器選項-Lpathname和-Rpathname告訴連接器鏈接時和運行時分別到哪個目錄中查找庫文件。動態鏈接庫文件中的所有符號在程序運行時都可見,而靜態鏈接僅僅把用到的符號內容鏈接到可執行文件中。始終將-l函數庫選項放在編譯命令行的最右邊。

8.小心interpositioning,自定義的標識符會遮蔽系統內部的標識符。

9.可執行文件a.out中包括a.out神奇數字、符號表等其他內容、bss段的大小(並不存儲bss段)、數據段(初始化的全局變量和靜態變量)、文本段(代碼)。程序運行時文本段會被mmap系統調用直接映射到進程地址空間,bss段和數據段合併,統稱爲數據區,在進入進程地址空間後全部清零。進程地址空間中的最低部分未被映射,數據區和堆棧區中間是共享庫的映射區域。

10.函數調用過程:1)實參按順序壓入棧中,2)保存返回地址eip到棧頂,call指令乾的,3)保存ebp到棧頂,4)設置ebp的值爲esp,5)保存寄存器內容,6)執行函數,7)恢復寄存器值,ebp->esp, pop ebp ,8)pop eip,esp+=參數個數*字長,ret指令乾的。

11.cache使用的是虛地址,當進程上下文切換時,需要刷新其內容。cache中每行有行中塊兒的虛擬塊地址和數據塊,塊大小一般爲32位。

12.動態申請的內存要記得釋放,否則會造成內存泄露。malloc(size),free(ptr),calloc(n, size)分配n個size大小的空間並清零,alloca(size)分配的空間不需要手動釋放,因爲其實在棧中分配的,在返回的指針作用域結束後會被自動回收。

13.現代計算機架構都要求內存對齊,可以是一個原子數據項不會垮cache塊或者頁的邊界。存取未對齊的數據會出現總線錯誤。而訪問未映射內存地址則會出現段錯誤,釋放一個內存塊兩次、釋放非動態分配的內存、或者釋放一個無效指針都會導致段錯誤。系統不支持在信號處理函數中調用庫函數。

14.標準io默認每次讀取一行字符,也就是需要回車把字符串輸入。當需要每次讀取一個字符時,可以使用system("stty raw");命令設置終端驅動模式爲單字符模式,完畢之後再使用system("stty cooked");恢復終端驅動爲行模式。也可以kbhit()非阻塞方法和輪詢,kbhit()函數即刻返回當前可讀的字符數,在頭文件conio.h中聲明。curses.h是字符的屏幕顯示控制函數庫。中斷驅動的io,通過設置SIGPOOL信號處理函數,處理每個字符輸入事件。記住,在信號處理函數中調用庫函數的結果是未定義的。

15.指針和數組在定義和聲明的時候不能混用,在表達式中和參數傳遞時可以通用。數組下標運算被編譯器轉換成指針運算,並自動調整步長爲元素大小,因此處理一維數組時,指針和數組速度相當。下標操作符的兩個操作數是可以互換位置的,但是實際很少用6[a]的形式,因爲沒什麼意義。在函數內部不能通過sizeof獲得參數數組到長度,因爲傳遞的是指針,得到的是指針類型的大小。

16.數組作爲參數時被轉換成指針,因此不能獲得其長度,需要使用約定來提示數組長度,如參數顯式指定或者在傳遞數組的末尾使用特殊的結束標記。而對於多維數組作爲形參,只有最高維的長度可以不給出,其他維的長度必須給出,把實參限制爲除最左邊一維外所有維都必須與形參匹配的數組。有了各維的長度信息,纔可以對數組下標或者指針地址正確的操作,得到準確的地址。

17.c++當中字符常量的類型是char,但在c中它們的類型是int。也就是c++中sizeof ‘a' 結果是1。

發佈了25 篇原創文章 · 獲贊 9 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章