zoukankan      html  css  js  c++  java
  • c语言复杂申明解释程序

    c语言复杂声明的解释

    目标:分析一个将c语言复杂申明解释为英语的一个程序

    首先介绍一种简单的读声明的方法,来源网络

    1.右左法则

    从标识符开始(或者最内层的结构,如果不存在标识符的话,通常出现于函数指针),首先向右看,直到遇到 ) 括号或者结束,看到什么就说出来;然后向左看,直到遇到 ( 括号或者回到行首,看到什么就说出来。跳出一层括号,重复上述过程:右看看,说出来;左看看,说出来。直到你说出变量的类型或者返回值(针对函数指针),也就表示你把声明都读完了。

    2.例子

    int *a[3];
    

    从标示符a开始,向右看,a是一个包含三个元素的数组,向左看数组的每个元素是指针,向右看到结尾了,向左看,指针指向int。综合:a是一个三元数组,数组的每个元素是指针,指向int。

    int (*a)[3];
    

    从标示符a开始,向右看,遇到(,向左看,a是一个指针,向右看,指针指向一个包含三个元素的数组,向左看,数组类型为int。

    int (*foo)();
    

    从标示符foo开始,向右看,遇到),向左看,foo是一个指针,想左看,指针指向一个无参数的函数,向右看,函数返回类型位int。

    int (*(*vtable)[])();
    

    这个比较复杂,还是从标示符table开始,向右看,遇到),向左看,table是一个指针,指针指向一个数组,向左看,数组的元素是指针,向右看,指针指向一个无参数的函数,向右看,函数的返回类型为int。

    实践完这些例子,基本就能明白右左法则。此法则能帮助我们快速的理解复杂声明,接下来将分析一个《c程序语言设计》中的一个复杂声明解释程序,但所用方法与此处的左右法则不同。

    此程序是基于声明符语法编写,其语法简化形式:

    dcl: 前面带有可选的direct-dcl
    direct-dcl: name,(dcl),direct-dcl(),direct-dcl[ ]
    简而言之,声明符dcl就是前面可能带有多个*的direct-dcl,direct-dcl可以是name,由一对圆括号括起来的dcl,后面跟有一对圆括号的direct-dcl,后面跟有用方括号括起来的direct-dcl。

    代码

    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    #define MAXTOKEN 100
    
    enum { NAME, PARENS, BRACKETS };
    
    void dcl(void);
    void dirdcl(void);
    int  gettoken(void);
    int  get_line(char s[], int lim);
    int  tokentype;
    char token[MAXTOKEN];
    char name[MAXTOKEN];
    char datatype[MAXTOKEN];
    char out[1000];           //衔接词
    
    #define BUFSIZE  1024
    char buf[BUFSIZE];
    char line[BUFSIZE];
    int bufp = 0;
    int linep = 0;
    
    int getch(void){
      if (bufp > 0 || (line[linep] !='\0'))
        return (bufp > 0) ? buf[--bufp] : line[linep++];
      else
        return EOF;}
    void ungetch(int c)
    {
      if (bufp >= BUFSIZE) 
        printf("ungetch: too many characters ");
      else
       buf[bufp++] = c;
    }
    
    int main(int argc, char* argv[]) 
    {
      get_line(line, BUFSIZE);
      while (gettoken() != EOF) {
        strcpy(datatype, token);
        out[0] ='\0';
        dcl();
        if (tokentype !='\n')
          printf("syntax error ");
        printf("%s: %s %s ", name, out, datatype);
      }
      return 0;
    }
    
    int gettoken(void) 
    {
      int c;
      char *p = token;
      while ((c = getch()) == ' ' || c == '\t')   //去除空格和换行符
    	;
      if (c == '(') {
        if ((c = getch()) == ')') {
          strcpy(token, "()");
          return tokentype = PARENS;
        } else {
          ungetch(c);
          return tokentype = '(';
        }
      } 
      else if (c == '[') {
        for (*p++ = c; (*p++ = getch()) != ']';)
          ;
        *p ='\0';
        return tokentype = BRACKETS;
      } 
      else if (isalpha(c)) {
        for (*p++ = c; isalnum(c = getch());)
          *p++ = c;
        *p ='\0';
        ungetch(c);
        return tokentype = NAME;
      } 
      else
        return tokentype = c;
    }
    int get_line(char s[], int lim)
    {
      int c, i;
      i = 0;
      while (--lim > 0 && (c = getchar()) != EOF && c !='\n')
        s[i++]=c;
      if (c == '\n')
    	s[i++]=c;
      s[i]='\0';
      return i;
    }
    void dcl(void)
    {
      int ns;
      for (ns = 0; gettoken() == '*';)
        ns++;
      dirdcl();
      while (ns-- > 0)
        strcat(out, " pointer to");
    }
    
    void dirdcl(void)
    {
      int type;
    
      if (tokentype == '(') {
        dcl();
        if (tokentype != ')')
          printf("error: missing ) ");
      } 
      else if (tokentype == NAME)
        strcpy(name, token);
      else
        printf("error: expected name or (dcl) ");
      while ((type = gettoken()) == PARENS || type == BRACKETS)
        if (type == PARENS)
          strcat(out, " function returning");
        else {
          strcat(out, " array");
          strcat(out, token);
          strcat(out, " of");
        }
    }
    
  • 相关阅读:
    virtualBox下面安装linux系统如何共享目录
    PHP中spl_autoload_register()函数
    PHP 5.5 新特性
    useradd密码无效
    Linux audit安全审计工具
    Javascript class获取回调函数数据
    RPi 3B 无线连接配置
    Refused to execute inline event handler because it violates the following Content Security Policy directive: "xxx". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...')
    options.html:1 Refused to load the script 'xxxx' because it violates the following Content Security Policy directive: "script-src 'self' blob: filesystem: chrome-extension-resource:".
    jQuery.Deferred exception: $.get is not a function TypeError: $.get is not a function
  • 原文地址:https://www.cnblogs.com/battzion/p/4217443.html
Copyright © 2011-2022 走看看