zoukankan      html  css  js  c++  java
  • 第五周读书笔记——读《程序员的自我修养》有感

    读《程序员的自我修养》有感

    花了几天时间,研读了《程序员的自我修养——链接、装载与库》。个人感觉它在操作系统的底层机制和运行原理可谓是一本好书。可惜个人修为不够、根底太浅,对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='';
     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] = '';
     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("
    ");
    170     return(0);
    171 }
    View Code

    这本书感觉日后还要再重读一次,可能感悟会更深一些。不过在一周时间内在这本书上搜刮了一些东西,也算是不枉一读了,幸甚幸甚。

  • 相关阅读:
    junit 4快速入门
    eclipse中的快速修复的另类用法(转,例子)
    eclipse 快速修复.(转)
    在Eclipse中导入dtd和xsd文件,使XML自动提示 (转)
    No grammar constraints (DTD or XML Schema)(转)
    web.xml报错Referenced file contains errors(转)
    Eclipse中编辑xml文件不自动提示怎么办(转)
    myeclipse 自定义xml模板,供新建xml文件时自动导入 (转)
    Junit 测试基础介绍!
    redis集群源码阅读 之 集群设置主从
  • 原文地址:https://www.cnblogs.com/redlogic/p/8721749.html
Copyright © 2011-2022 走看看