对于声明,应该按下面的步骤来进行解释:

1) 声明从它的名字开始读取,然后按照优先级顺序依次读取

2) 优先级顺序

a) 括号括起来的部分

b) 后缀操作符,()表示函数,[]表示数组

c) 前缀操作符,*表示指针

3) 如果const或volatile关键字后面紧跟类型说明符,那么他作用于类型说明符,其他情况下,作用于其左边紧邻的指针星号。

根据这个原则,我们可以得到下面的代码

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAXTOKENS 100
#define MAXTOKENLEN 64 enum type_tag { IDENTIFIER, QUALIFIER, TYPE }; struct token {
char type;
char string[MAXTOKENLEN];
}; int top = -;
struct token stack[MAXTOKENS];
struct token that; #define pop stack[top--]
#define push(s) stack[++top] = s enum type_tag classify_string(void) {
char *s = that.string;
if (!strcmp(s, "const")){
strcpy(s, "read-only");
return QUALIFIER;
}
if (!strcmp(s, "volatile")) return QUALIFIER;
if (!strcmp(s, "void")) return TYPE;
if (!strcmp(s, "char")) return TYPE;
if (!strcmp(s, "signed")) return TYPE;
if (!strcmp(s, "unsigned")) return TYPE;
if (!strcmp(s, "short")) return TYPE;
if (!strcmp(s, "int")) return TYPE;
if (!strcmp(s, "long")) return TYPE;
if (!strcmp(s, "float")) return TYPE;
if (!strcmp(s, "double")) return TYPE;
if (!strcmp(s, "struct")) return TYPE;
if (!strcmp(s, "union")) return TYPE;
if (!strcmp(s, "enum")) return TYPE;
return IDENTIFIER;
} void gettoken (void)
{
char *p = that.string; while ((*p = getchar()) == ' '); if (isalnum(*p)){ while (isalnum(*++p = getchar()));
ungetc(*p, stdin);
*p = '\0';
that.type = classify_string();
return;
} if (*p == '*') {
strcpy(that.string, "pointer to");
that.type = *p;
return;
}
that.string[] = '\0';
that.type = *p;
return;
} void read_to_first_identifier (){
gettoken();
while (that.type != IDENTIFIER) {
push(that);
gettoken();
}
printf("%s is ", that.string);
gettoken();
} void deal_with_arrays() {
while (that.type == '[') {
printf("array ");
gettoken();
if (isdigit(that.string[])) {
printf("0..%d ", atoi(that.string)-);
gettoken();
}
gettoken();
printf("of ");
}
} void deal_with_function_args() {
while (that.type != ')') {
gettoken();
}
gettoken();
printf("function returning ");
} void deal_with_pointers () {
while (stack[top].type == '*') {
printf("%s ", pop.string);
}
} void deal_with_declarator() { switch(that.type){
case '[' :deal_with_arrays();break;
case '(' :deal_with_function_args();
} deal_with_pointers(); while (top >= ) {
if (stack[top].type == '(') {
pop;
gettoken();
deal_with_declarator();
}else {
printf("%s ", pop.string);
}
}
}

int (*a)()

结果:

a is pointer to function returning int

过程:
读入int
读入(
读入*
读入a
a是标识符,退出开始的循环
输出a is
读入),由于有)暂不读入后面字符,弹出*,输出pointer to,
一直弹出,直到(则继续读取后面的字符(,
因为读到(,输出function returning.

int *a()

结果:

a is function returning pointer to int

过程:

读入int
读入*
读入a
a是标识符,退出开始的循环
输出a is
读入(判断出a是个函数输出function returning
读取*,输出pointer to
读取int,输出int

类型解释器——C专家编程读书笔记的更多相关文章

  1. c专家编程读书笔记

    无论在什么时候,如果遇到malloc(strlen(str));,几乎可以直接断定他是错误的,而malloc(strlen(str)+1):才是正确的: 一个L的NUL哟关于结束一个ACSII字符串: ...

  2. 《android开发进阶从小工到专家》读书笔记--HTTP网络请求

    No1: 客户端与服务器的交互流程: 1)客户端执行网络请求,从URL中解析出服务器的主机名 2)将服务器的主机名转换成服务器的IP地址 3)将端口号从URL中解析出来 4)建立一条从客户端与Web服 ...

  3. python高级编程读书笔记(一)

    python高级编程读书笔记(一) python 高级编程读书笔记,记录一下基础和高级用法 python2和python3兼容处理 使用sys模块使程序python2和python3兼容 import ...

  4. C++Windows核心编程读书笔记

    转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...

  5. Node.js高级编程读书笔记Outline

    Motivation 世俗一把,看看前端的JavaScript究竟能做什么. 顺便检验一下自己的学习能力. Audience 想看偏后台的Java程序员关于前端JavaScript的认识的职业前端工程 ...

  6. CSAPP 并发编程读书笔记

    CSAPP 并发编程笔记 并发和并行 并发:Concurrency,只要时间上重叠就算并发,可以是单处理器交替处理 并行:Parallel,属于并发的一种特殊情况(真子集),多核/多 CPU 同时处理 ...

  7. Java并发编程读书笔记(一)

    ----------------------------------------------<Java并发编程实战>读书笔记-------------------------------- ...

  8. unix环境高级编程-读书笔记与习题解答-第一篇

    从这周开始逐渐的进入学习状态,每天晚上都会坚持写c程序,并且伴随对这本书的深入,希望能写出更高质量的读书笔记和程序. 本书的第一章,介绍了一些关于unix的基础知识,在这里我不想去讨论linux到底是 ...

  9. UNIX网络编程--读书笔记

    会集中这段时间写UNIX网络编程这本书的读书笔记,准备读三本,这一系类的文章会不断更新,一直会持续一个月多,每篇的前半部分是书中讲述的内容,每篇文章的后半部分是自己的心得体会,文章中的红色内容是很重要 ...

随机推荐

  1. mysql:键缓存

    myisam的主要优化参数: key_buffer_size - 这对MyISAM表来说非常重要,是用来设置整个MySQL中常规Key Cache的大小.一般来说,如果MySQL运行在32位平台,此值 ...

  2. Swift游戏实战-跑酷熊猫 14 熊猫打滚

    这节内容我们来实现熊猫打滚.思路是这样的,当熊猫起跳时记录他的Y坐标,落到平台上的时候再记录它的Y坐标.两个坐标之间的差要是大于一定数值就判断它从高处落下要进行打滚缓冲.至此跑酷熊猫已经像一个游戏的样 ...

  3. PostgreSQL configuration file postgresql.conf recommanded settings and how it works

    1        Set max_connections to three times the number of processor cores on the server. Include vir ...

  4. Extjs4.x完美treepanel checkbox无限级选中与取消

    注:当node选中, childNodes逐级全部选中. parentNode当子node全部选中时逐级自动选中,nodes未全部选中, parentNode逐级自动取消选中 在javascript中 ...

  5. extjs4.0下的日期控件的星期显示为y的解决办法

    没有修改的时候的问题: 今天第一次写博客,就记录一下以前extjs4.2下运用日期组件的星期显示问题,当时找了n久,可能是extjs4.2才出来没多久,没有多少人发现这个问题或者说很少有人将Extjs ...

  6. editPlus修改默认的文件编码

  7. <c:if>标签的使用

    <c:if>标签用来在页面中实现条件化的判断功能.它的主要目的就是替换Java脚本中的if语句,来实现页面内容的条件化输出功能.这个标签所进行的判读主要是依据表达式来进行的,如果该表达式的 ...

  8. sql 中各种锁随记

    一. 为什么要引入锁    多个用户同时对数据库的并发操作时会带来以下数据不一致的问题:    丢失更新  A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系 ...

  9. 有关dwr推送的笔记

    想做一个web推送相关的东东,昨天搞了一天,终于把这些杂乱的配制弄清了,今天写出来方便以后记住,也方便大家看一下吧 1:引入dwr包,我用的是maven <dependency> < ...

  10. VC6.0 error LNK2001: unresolved external symbol _main(转)

    学习VC++时经常会遇到链接错误LNK2001,该错误非常讨厌,因为对于编程者来说,最好改的错误莫过于编译错误,而一般说来发生连接错误时,编译都已通过.产生连接错误的原因非常多,尤其LNK2001错误 ...