c專家程式設計
第一章1,在函式定義中形參的數量最大是31個,函式呼叫時實參的數量最大也是31個,一條源**行裡至少可以有509個字元,在表示式中可支援32層巢狀的括號。
2,const float * 型別是指向乙個具有const限定符的float型別的指標。
3,const int *limitp=&limitp;limitp是乙個指向常量整型的指標,這個指標不能用於修改這個整型數,但是在任何時候,這個指標本身的值確可以改變,這樣它就指向了不同的位址,,對它
解除引用操作時就會得到乙個不同的值。
4,const和*組合通常只用於在陣列形式的引數中模擬傳值呼叫。它聲稱「我給你乙個指向它的指標,但你不能修改它」。這個約定類似於void *用法。理論上可以用於任何情形,但通常會限制於把指標
從乙個型別轉換為另一種型別。
5,盡量不要使用無符號型別,因為負數會被翻譯成無窮大。只有在使用位段和二進位制**時,才可以用無符號數。應該在表示式中使用強制型別轉化,使運算元均為有符號或無符號,這樣就不必由編譯器
選擇結果的型別。
6,乙個l的null用於結束乙個ascii字串,兩個l的null用於空指標。
第二章1,在c語言中乙個符號要麼全域性可見,要麼對其它檔案都不可見。
2,c語言的過載:
static:在函式內部即區域性變數+static,表示該變數值在各個呼叫間一直保持延續性;在函式一級即函式名前加static,表示該函式只對本檔案可見。
extern:用於函式定義,表示全域性可見(屬於冗餘的因為預設的就是全域性可見),用於變數表示它在其它地方定義。
void:作為函式返回型別,表示不返回任何值;在指標宣告中,表示通用指標的型別;位於引數列表中,表示沒有引數。
*:乘法運算子;用於指標,間接引用;在宣告中表示指標。
&:位的and操作符;取位址操作符;
():在函式定義中,包圍形式參數列;呼叫乙個函式;改變表示式的運算次序;強制型別轉化;定義帶引數的巨集;包圍sizeof操作符的運算元。
3,優先順序問題:.的優先順序高於*;->操作符用於消除這個問題;高於*;函式()高於*
4,在c語言中,自動變數在堆疊中分配記憶體,但包含自動變數函式或**塊退出時,它所占用的記憶體便被收回。解決方法:返回乙個指向字串常量的指標;使用全域性宣告陣列;使用靜態陣列;
顯示分配一些記憶體,儲存返回的值;
第三章1,int (*foo()):返回的是乙個指向陣列的指標;
2,typedef是一種型別引入新的名字,應該用在陣列,結構,指標以及函式的組合型別。可移植型別
第四章1,c語言中的物件必須有且有乙個定義,但它可以有多個extern宣告。定義只能出現在乙個地方:確定物件的型別並且分配記憶體,用於建立新的物件。宣告可以多次出現:描述物件的型別
,用於指代其他地方定義的物件。宣告相當於普通的宣告,它所宣告的並非自身,而是描述其他地方建立的物件。定義相當於特殊的宣告,它為物件分配記憶體。
2,x=y;在當前環境裡,符號x的含義是x所代表的位址稱為左值,左值在編譯時可知,左值表示儲存結果的地方。符號y的含義是y所代表的位址的內容,稱為右值,在執行時才知。
第五章1,預處理器-》語法和語義檢查器-》**生成器-》匯程式設計序-》優化器-》鏈結器
2,動態鏈結的主要目的是把程式與特定的函式庫版本中分離開來,由系統向程式提供乙個介面,該介面保持穩定,不隨時間和作業系統的後續版本發生變化。
3,動態鏈結檔案的副檔名是.so,而靜態庫檔案的副檔名是.a;通過-lthread選項,告訴編譯鏈結到libthread.so,傳給c編譯器的命令列引數裡並沒有提到函式庫的完整路徑名及函式庫目錄中該檔案的
完整名字。實際上,編譯器被告知根據選項-lname連線到相應的函式庫。
4,編譯器期望在確定的目錄找到庫,在鏈結時使用-lpathname和—rpathname選項告訴鏈結器一些其他的目錄。
5,觀察標頭檔案,確認所使用的函式庫
6,可以在ld程式中使用-m選項,讓鏈結器產生乙個報告。使用ldd命令,列出可執行檔案的動態依賴集,這條命令會告訴你動態鏈結程式所需要的函式庫。
7,鏈結器把指令直接從檔案拷貝到記憶體中(一般使用mmap())
8,可執行檔案中段在記憶體中的布局:堆疊段(區域性於函式的資料,儲存區域性變數,臨時資料,傳遞到函式好著呢個的引數)-》bss段(未初始化的資料)-》資料段(經過初始化的資料,經過初始化的全域性和靜態變數)-》文字段(可執行檔案的指令)
9,c程式執行時的資料結構有好幾種:堆疊,活動記錄,資料,堆等。堆疊為函式內部宣告的區域性變數儲存空間;進行函式呼叫時,堆疊儲存與此有關的一些維護性資訊。
第七章1,虛擬記憶體通過頁的形式組織,頁是作業系統在磁碟和記憶體之間移動或進行保護的單位。在磁碟中有個特殊的交換區,用於儲存從記憶體中換出的程序,交換區一般是物理記憶體的幾倍,只有使用者程序才會
換進換出。程序只能操作位於物理記憶體中的頁面。
2,堆區域用於動態分配的儲存,通過malloc分配,通過指標訪問。堆中的東西都是匿名的,不能按名字直接訪問,只能通過指標間接訪問。堆記憶體分配的大小總是經過對齊是2的乘方。堆的末端有乙個
稱為break的指標來標識。當堆管理更多記憶體時可以系統呼叫brk和sbrk來移動break指標。
3,觀察記憶體洩漏是兩個步驟:首先用swap命令觀察還有多少可用空間:/usr/sbin/swap -s;在一兩分鐘內置入該命令三到四次,看看可用交換區是否在減少或/usr/bin/*stat netstat,vmstat
發現不斷有記憶體被分配且從未被釋放。第二步是確定可疑程序:pa -lu;來顯示所有程序的大小。
4,最終可能導致段錯誤的常見程式設計錯誤是:壞指標錯誤:在指標賦值前使用,向函式庫傳遞乙個壞指標,釋放後仍然訪問它的內容可以釋放後賦值為null;越陣列邊界寫入資料;
指標釋放引起的錯誤:釋放乙個記憶體塊兩次,釋放未曾分配的記憶體,釋放仍在使用的記憶體,釋放無效指標。
5,在遍歷鍊錶時正確釋放元素的方式是使用臨時變數儲存下乙個元素的位址。
第九章1,陣列下標的引用總是可以寫成「乙個指向陣列的起始位址的指標加上偏移量」;在表示式中指標和陣列是可以互換的,它們在編譯器裡的最終形式都是指標,都可以進行取下標操作。
2,編譯器自動把下標值的步長調整到陣列元素的大小。
3,把函式的形參的陣列和指標等同起來是處於效率的考慮。
4,在c的多維陣列中,最右邊的下標是最先變化的這個約定稱為「行主序」
第十章1,a[i][j]:在記憶體中首先找到a[i]的位置,然後偏移[j]取得字元a[i][j]被編譯器解析為:*(*(a+i)+j)
2,無法直接從函式返回乙個陣列,但可以讓函式返回乙個指向任何資料結構的指標。int (*func())[20];返回乙個指向包含20個int元素的陣列的指標。
第十一章
1,物件導向程式設計的特點是繼承和動態繫結。c++通過類的派生支援繼承,通過虛函式支援動態繫結。虛函式提供了一種封裝類體系的實現細節的方法。
2,c語言允許使用者定義新的型別(struct,enum)來支援抽象。封裝:把相關的型別,資料和函式組合在一起。
3,類就是使用者定義型別加上所有對該型別進行的操作。friend類的函式,不屬於類的成員函式但可以像成員函式一樣訪問類的private和protected值
C專家程式設計
說到c語言,首稱 c程式語言 這是一本入門和進修均可的書籍,值得讀三遍以上,方才有味。進修書籍如 c專家程式設計 是一本c語言較高層次的書,是成為c語言專家的必經之路。我自以為達到了一定的 程度,才開始學習這本書的。人言,c語言是一門藝術,需要多年歷練才能達到較為完善的境界,此言不虛。c語言進修書籍...
C 專家程式設計
2011.9.4 c 專家程式設計 1 容易混淆的 const 關鍵字const 並不能把乙個變數變為常量,它修飾的符號僅表示該符號的值不能被賦值,也就意味著唯讀不可寫,但它並不能防止通過程式內部 甚至外部,其它函式 的方法來修改它。const 最有用支出是用來限定函式的形參,這樣該函式不會修改實參...
c專家程式設計
pag13 關於替代庫函式 標準規定編譯器只有在違反語法規則和約束條件的情況下才能產生錯誤資訊。所有c語言標準標頭檔案中宣告的識別符號均保留,所以不能宣告乙個叫做malloc 的函式,因為在標準標頭檔案裡已經有乙個函式以此為名。但由於這個規定不是約束條件,因此可以違反他。所以可以用自己宣告的函式來替...