• 类型解释器——C专家编程读书笔记


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

    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 = -1;
    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 = '';
      that.type = classify_string();
      return;
     }
    
     if (*p == '*') {
      strcpy(that.string, "pointer to");
      that.type = *p;
      return;
     }
     that.string[1] = '';
     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[0])) {
       printf("0..%d ", atoi(that.string)-1);
       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 >= 0) {
      if (stack[top].type == '(') {
       pop;
       gettoken();
       deal_with_declarator();
      }else {
       printf("%s ", pop.string);
      }
     }
    }
    View Code

    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

  • 相关阅读:
    日志配置
    Mybaties核心配置文件
    配置3
    写了两个数据获得方式----费劲周折
    applicationContext
    配置2
    Django-缓存的配置
    RabbitMQ的工作模式
    centos下保留python2安装python3
    python位运算
  • 原文地址:https://www.cnblogs.com/studynote/p/3449590.html
Copyright © 2020-2023  润新知