第五週讀書筆記——讀《程序員的自我修養》有感

讀《程序員的自我修養》有感git

花了幾天時間,研讀了《程序員的自我修養——連接、裝載與庫》。我的感受它在操做系統的底層機制和運行原理可謂是一本好書。惋惜我的修爲不夠、根底太淺,對Linux一樣不熟悉。等之後有積累了再來回讀一番。程序員

做者在序言裏這樣提出:計算機思想其實都是相通的,由於它們的核心思想是穩定不變的。這在我看來很大程度上是因爲底層架構決定的,現行的計算機大多仍是馮·諾依曼架構(量子計算機還有待成熟),所以萬變不離其宗。算法

做者是個極愛鑽研的人,到處可見一斑。對於最簡單的入門程序hello world」,做者對其提出了一連串的問題,這讓我大感意外。「C語言程序爲何要被編譯後才能運行?」、「編譯過程當中發生了什麼?」、「不一樣狀況下的編譯結果是否相同」。如此簡單的程序背後每每蘊含着複雜機制,若是單單是做爲一個編譯器的使用者,天然沒必要考慮這一切。可是若是但願進一步對此有了解,乃至可以創造出更好的機制,那麼這都是不可或缺的。從「預處理」、「編譯」到「彙編」再到「連接」,編譯器開始爲咱們所理解。原來「#define」,「#include」在一開始就會被展開和替代。而在掃描過程當中進行源代碼的生成,以後再進行一步步的工做。於此咱們能夠見微知著,一部分原來有些強硬的規範其實有着深入的內涵。例如宏語句使用時的注意事項(儘可能加個括號),調試時「莫名其妙」被省略的變量(編譯器提供的代碼優化),開數組的時候全局變量每每能比局部變量分配更大的空間(堆棧與靜態存儲的不一樣)。這些小細節不是空穴來風、而是底層架構在上層的具象反映。而掌握底層架構,可以使咱們更加精細地利用計算機的功能。編程

計算機科學有至關一部分須要依賴於自個人實踐。做者爲了瞭解操做系統及裝載等這些關鍵的技術,他從頭寫了一個很小的內核、裝載器及一個簡單的運行庫,作成了一個簡單但較爲完備的操做系統。儘管這些沒什麼直接收益(讓GPA增長是不可能的,讓本身發paper也是不可能的……),可是能夠從中舉一反三。我的做業時寫簡單的hash的時候和大數組搜索算法時由於好久不動,致使碼了好久,因此說僅僅是領悟思想是不夠的,還要付諸實踐。看這本書的時候看到了語法樹部分,感受它比數據結構課上所講的中序表達式二叉樹很爲類似,就順手寫了個解釋C語言代碼(極簡版)的代碼,中間參考了別人的一些想法(主要是《C專家編程》),完成後讓本身很有所得(儘管這無法計入成績(*^_^*))。數組

 

  1 #include"stdio.h"
  2 #include"string.h"
  3 #include"ctype.h"
  4 #include"stdlib.h"
  5 
  6 #define MAXTOKENS 100        //設置語句中標識符的最大數量100
  7 #define MAXTOKENLEN 64        //設置標識符的最大長度64
  8 
  9 enum type_tag {IDENTIFIER,QUALIFIER,TYPE};        //IDENTIFIER=0,QUALIFIER=1,TYPE=2
 10 
 11 struct token    //結構體:標識符(token)
 12 {
 13     char type;        //type:數據類型
 14     char string[MAXTOKENLEN];    //string[MAXTOKENLEN]:存儲標識符名稱的數組
 15 };
 16 
 17 int top=-1;
 18 struct token stack[MAXTOKENS];        //stack[]:存儲整句語句的標識符的數組(堆棧)
 19 struct token these;        //these:臨時存儲單個標識符的變量
 20 
 21 #define pop stack[top--]
 22 #define push(s) stack[++top] = s    //push(s):將變量s壓入stack數組頂端
 23 
 24 enum type_tag classify_string(void)        /*推斷標識符的類型*/
 25 {
 26     char *s = these.string;            /*用指針s代替these的string數組使用(簡潔)*/
 27     if(!strcmp(s,"const"))            //若是string中是"const"
 28     {
 29         strcpy(s,"read-only");        //將s中的"const"翻譯爲"read-only"
 30         return(QUALIFIER);
 31     }
 32     if(!strcmp(s,"volatile"))        
 33         return(QUALIFIER);
 34     if(!strcmp(s,"void"))            //下面一系列if判斷,返回type:數據類型說明
 35         return(TYPE);
 36     if(!strcmp(s,"char"))
 37         return(TYPE);
 38     if(!strcmp(s,"signed"))
 39         return(TYPE);
 40     if(!strcmp(s,"unsigned"))
 41         return(TYPE);
 42     if(!strcmp(s,"short"))
 43         return(TYPE);
 44     if(!strcmp(s,"int"))
 45         return(TYPE);
 46     if(!strcmp(s,"long"))
 47         return(TYPE);
 48     if(!strcmp(s,"float"))
 49         return(TYPE);
 50     if(!strcmp(s,"double"))
 51         return(TYPE);
 52     if(!strcmp(s,"struct"))
 53         return(TYPE);
 54     if(!strcmp(s,"union"))
 55         return(TYPE);
 56     if(!strcmp(s,"enum"))
 57         return(TYPE);
 58     return(IDENTIFIER);
 59 }
 60 
 61 void gettoken(void)            /*讀取下一個標記到"these"*/
 62 {
 63     char *p = these.string;
 64 
 65     /*跳過空白字符*/
 66     while((*p = getchar()) == ' ');
 67 
 68     if(isalnum(*p))            /*輸入的字符以A-Z,0-9開頭*/
 69     {
 70         while(isalnum(*++p = getchar()));
 71         ungetc(*p,stdin);
 72         *p='\0';
 73         these.type = classify_string();
 74         return;
 75     }
 76 
 77     if(*p == '*')
 78     {
 79         strcpy(these.string,"pointer to");
 80         these.type = '*';
 81         return;
 82     }
 83     these.string[1] = '\0';
 84     these.type = *p;
 85     return;
 86 }
 87 
 88 /*理解全部分析過程的代碼段*/
 89 void read_to_first_identifier(void)
 90 {
 91     gettoken();
 92     while(these.type != IDENTIFIER)
 93     {
 94         push(these);
 95         gettoken();
 96     }
 97     printf("%s is ", these.string);
 98     gettoken();
 99     return;
100 }
101 
102 void deal_with_arrays(void)
103 {
104     while(these.type == '[')
105     {
106         printf("array ");
107         gettoken();            /*數字或']'*/
108         if(isdigit(these.string[0]))
109         {
110             printf("0..%d ",atoi(these.string)-1);
111             gettoken();        /*讀取']'*/
112         }
113         gettoken();        /*讀取']'以後的一個標記*/
114         printf("of ");
115     }
116     return;
117 }
118 
119 void deal_with_function_args(void)
120 {
121     while(these.type !=')')
122     {
123         gettoken();
124     }
125     gettoken();
126     printf("function returning ");
127     return;
128 }
129 
130 void deal_with_pointers(void)
131 {
132     while(stack[top].type == '*')
133     {
134         printf("%s ", pop.string);
135     }
136     return;
137 }
138 
139 void deal_with_declarator(void)        /*處理標識符以後可能存在的數組或函數*/
140 {
141     switch(these.type)
142     {
143     case '[' : deal_with_arrays();break;
144     case '(' : deal_with_function_args();
145     }
146 
147     deal_with_pointers();
148 
149     while(top >= 0)            /*處理在讀入到標識符以前壓入堆棧中的符號*/
150     {
151         if(stack[top].type == '(')
152         {
153             pop;
154             gettoken();
155             deal_with_declarator();
156         }
157         else
158         {
159             printf("%s ", pop.string);
160         }
161     }
162     return;
163 }
164 
165 int main(void)
166 {
167     read_to_first_identifier();        /*將標記壓入堆棧中,直到碰見標識符*/
168     deal_with_declarator();
169     printf("\n");
170     return(0);
171 }
View Code

 

 

 

這本書感受往後還要再重讀一次,可能感悟會更深一些。不過在一週時間內在這本書上搜颳了一些東西,也算是不枉一讀了,幸甚幸甚。數據結構

相關文章
相關標籤/搜索