《C專家程式設計》讀書筆記(1)

2021-09-16 18:29:48 字數 2534 閱讀 2205

早期的unix系統並不是用c語言寫的,unix的出現要比c語言早。

組合語言編寫的unix很笨拙,編寫資料結構時浪費大量時間,且系統難以除錯,理解困難。

thompson(貝爾實驗室的研究人員)利用高階語言的特點(對比組合語言的缺點),但又不想執行效率底下,嘗試用fortran進行一番簡短而又不成功的嘗試,他建立了b語言,將用於研究語言的bcpl作了簡化,使b的直譯器能常駐於pdp-7只有8kb大小的記憶體中。由於硬體系統的記憶體限制,它只允許放置直譯器,而不是編譯器,因此阻礙了使用b語言進行unix自身的系統程式設計。

編譯器的效率包括執行效率(**的執行速度)和編譯效率(產生可執行**的速度)。除了一些開發和學習環境之外,執行效率起決定性作用。

有很多編譯優化措施會延長編譯時間,卻能縮短執行時間。

還有一些優化措施(諸如清除無用**和忽略執行時檢查等)既能縮短編譯時間,又能減少執行時間,同時還能減少記憶體的使用量。但是這些優化措施的不利之處在於可能發現程式中的無效的執行結果,優化措施本身在轉換**時是非常謹慎,如果程式設計師編寫了無用的**(如:越過陣列邊界引用物件,因為他們「知道」附近有他們需要的變數)就可能引發錯誤。

編譯器設計者通常會提供一些編譯器選項,每個程式設計師可以選擇自己想要的優化措施。而dennis rithie所創造的注重效率的「new b」卻獲得了成功,充分證明了編譯器設計者的這條金科玉律。

b語言通過省略一些特性(巢狀過程和一些迴圈結構),對bcpl語言作了簡化,並發揚了「引用陣列元素相當於對指標加上偏移量的引用」這個想法,同時保持了bcpl語言(void?)無型別這個特點,它僅有的運算元就是機器的字。thomposon發明了++和–操作符,並把它加入到pdp-7的b編譯器中。它們在c語言中依然存在,並不是由於pdp-11存在對應的自動增/減位址模型,自動增/減機制的出現早於pdp-11硬體系統的出現。儘管在c語言中:

*p++

=*s++

可以極其有效地被編譯為pdp-11**:

moveb (r0)+, (r1)+
前者並不是根據後者特意設計。

2023年開發平台轉移到pdp-11以後,無型別語言很快就顯得不合時宜了,這種處理器以硬體支援幾種不同長度的資料型別為特色,而b語言無法表達不同的資料型別,效率也是乙個問題,迫使thompson在pdp-11上重新使用組合語言實現了unix。dennis ritche利用pdp-11的強大效能,創立了解決多種資料型別和效率的「new b」語言(很快變成了「c」),它採用了編譯模式而不是解釋模式,並引入了型別系統,每個變數在使用前必須先宣告。

增加型別系統的主要目的是幫助編譯器設計者區分新型pdp-11機器所擁有的不同資料型別,如單精度浮點數、雙精度浮點數和字元等。與其他一些語言如pascal形成了鮮明的對比。在pascal中,型別系統的目的是保護程式設計師,防止他們在資料上進行無效的操作。由於設計哲學不同,c語言排斥強型別,它允許程式設計師需要時可以在不同型別的物件間賦值。型別系統從未在可用性方面進行過認真的評估和嚴格的測試。許多c程式設計師仍然認為「強型別」只不過是增加了敲擊鍵盤的無用功。

開始幾年c語言的主要客戶就是編譯器設計者,許多特性是為了編譯器設計者而建立的,根據編譯器設計者的思路而發展形成的語言特性有:

陣列下標從0而不是1開始

​ 這是因為偏移量的概念根深蒂固於編譯器設計者的心中

c語言的基本資料型別直接與底層硬體相對應

​ 不像fortran,c語言不存在內建的複數型別,某種語言要素如果底層硬體沒有提供直接的支援,那麼編譯器設計者不會在它上面浪費任何精力,c語言一開始並不支援浮點型別,直到硬體系統能夠直接支援浮點數之後才增加了對它的支援。

auto關鍵字顯然是擺設

​ 這個關鍵字只對建立符號表入口的編譯器設計者有意義。它的意思是「在進入程式塊時自動進行記憶體分配」(與全域性靜態分配或在堆上動態分配相反)。其他程式設計師不必操心auto這個關鍵字,它是預設的變數記憶體分配模式(預設)。

表示式中的陣列名可以看作時指標

​ 將陣列看作指標,把它們傳遞到乙個函式時不必忍受必須複製所有陣列內容的低效率。但是,陣列和指標並不是在任何情況下都是等效的(書第4章)

float被自動擴充套件為double

​ 在ansi c中情況不再如此。早期的unix程式中,float轉換成double代價非常小,只要在後面增加乙個每個位均為0的字即可,如果要轉換回來,去掉第二個字就可以;此外,在某些pdp-11的浮點數硬體表示形式中有乙個運算模式位(mode bit), 可以只進行float的運算,也可以只進行double的運算(也就是說如果要進行這兩種方式的運算需要改變運算模式位),因此早期都是將運算模式固定為double是比較方便的,省得編譯器設計者去跟蹤它的變化。

不允許巢狀函式(函式內部包含另乙個函式的定義)

​ 簡化編譯器,稍微提高c程式的執行時組織結構。

​ 能夠為編譯器設計者提供線索:程式中的哪些變數是經常使用的,這樣就可以把它們存放到暫存器中。這個設計可以說是乙個失誤,如果讓編譯器在使用各個變數時自動處理暫存器的分配工作,要比一經宣告就把這類變數在生命期內始終保留在暫存器裡要好。這雖然簡化了編譯器,卻把包袱丟給了程式設計師。

unix系統的廣泛使用,使得c語言茁壯成長。c語言對直接由硬體支援的底層操作的強調,帶來了極高的效率和移植性,反過來也幫助unix獲得了巨大的成功。

C專家程式設計 讀書筆記1

1.早期的c 1972 3 k r c 1976 9 ansi c 1983 9 ansi 美國國家標準化組織 2.const的使用 const int limit 10 const int limitp limit int i 15 limitp i printf d n limitp 以上程式,...

《C 專家程式設計》讀書筆記

前言 程式設計挑戰 計算機日期 第二章 這不是bug,而是語言特徵 switch的乙個bug break中斷了什麼 第三章 分析c語言宣告 程式設計挑戰 把c 語言的宣告翻譯成通俗的語言 include include include include define max len 100 enum ...

《C專家程式設計》讀書筆記

第一章 const float 表示乙個指向float型別常量的指標 第二章 1.在c語言中const並非真正表示 常量 在陣列定義與case中不可以使用 2.case的一些問題 2 3 main 15 這段 列印出來的是 3.函式可見性 void sb any where 2 extern voi...