• C语言声明的优先级规则


    C语言声明的有时候又些难以理解,如果不理解它的优先级规则,就经常难以分析,下面列出其规则:

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

    B  优先级从高到低依次是:

        B.1   声明中被括号起来的那部分

        B.2   后缀操作符:

            括号()表示这是一个函数,方括号[]表示这是一个数组

        B.3  前缀操作符:星号*表示 “指向...的指针”

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

    《C专家编程》中通过图表分析C语言的声明,如下图

    C声明解析代码

    /* (Expert C Programming) */
    #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];
    };


    struct token stack[MAXTOKENS];
    struct token this;

    #define pop stack[top--]
    #define push(s) stack[++top] = s;

    int top=-1;
    enum type_tag classify_string(void)
    {
    char *s = this.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 = this.string;
    while((*p = getchar()) == '')
    ;

    if(isalnum(*p))
    {
    while(isalnum(*++p = getchar()))
    ;
    ungetc(*p,stdin);
    *p = '\0';
    this.type = classify_string();
    return;
    }

    if(*p == '*')
    {
    strcpy(this.string,"pointer to ")
    ;
    this.type = '*';
    return;
    }

    this.string[1] = '\0';
    this.type = *p;
    return;
    }

    read_to_first_identifier()
    {
    gettoken();
    while(this.type != IDENTIFIER)
    {
    push(this);
    gettoken();
    }
    printf("%s is ",this.string);
    gettoken();
    }

    deal_with_arrays()
    {
    while(this.type == '[')
    {
    printf("array");
    gettoken();
    if(isdigit(this.string[0]))
    {
    printf("0..%d",atoi(this.string)-1);
    gettoken();
    }
    gettoken();
    printf(" of ");
    }
    }

    deal_with_function_args()
    {
    while(this.type != ')')
    {
    gettoken();
    }
    gettoken();
    printf("function returning ");
    }

    deal_with_pointers()
    {
    while(stack[top].type == '*')
    {
    printf("%s ",pop.string);
    }
    }

    deal_with_declarator()
    {
    switch(this.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);
    }
    }

    int main()
    {
    read_to_first_identifier();
    deal_with_declarator();
    printf("\n");
    return 0 ;
    }



  • 相关阅读:
    Android 源代码解析 之 setContentView
    poj 2484 A Funny Game
    BlueDroid代码分析之GKI
    Chromium多线程模型设计和实现分析
    关于template 的23个问题
    Struts2 动态结果集
    沁园春&#183;咏史
    android中常见的内存泄漏和解决的方法
    Spring整合freemarker发送邮件
    [struts2学习笔记] 第三节 创建struts 2 HelloWorld所需的六个步骤
  • 原文地址:https://www.cnblogs.com/Quincy/p/2268350.html
Copyright © 2020-2023  润新知