C语言声明的理解

时间:2021-10-29 08:35:02

优先级规则分析
A.声明从他的第一个标识符(名字)开始读取,然后按照优先级顺序依次读取:
B 优先级从高到低依次是:
    B.1声明中被括号括起来的那部分
    B.2后缀操作符:
          括号()表示这是一个函数,而方括号[]表示这是一个数组。
    B.3前缀操作符:星号*表示“指向...的指针”
C 如果const和(或)volatile关键字的后面紧跟类型说明符(如int,long等),那么它用做子类型说明符。在其他情况下,    const和(或)volatile关键字作用于它左边的临近的指针星号。
例:
    char * const *(*next)();

A             首先,看变量名(标识符)“next”,并注意到它直接被括号所括住
B.1          所以先把括号里的东西作为一个整体,得出“next是一个指向...的指针”
B             然后考虑括号外面的东西,在星号前缀和括号后缀之间作出选择
B.2          B.2规则告诉我们优先级较高的是右边的函数括号,所以得出“next是一个函数指针,指向一个返回...的函数”
B.3          然后,处理前缀“*”,得出指针所指的内容
C             最后,把“char * const”解释为指向字符的常量指针

 

更直观一点可以看下图

C语言声明的理解

 

所以这个声明表示“next”是一个指针,它指向一个函数,该函数返回另一个指针,该指针指向一个类型为char的常量指针。


例子2  char *(* c[10]) (int **p)

剩余的声明

下一次要进行的步骤

结果

从最左边的标识符开始

 

 

char *(* c[10])(int **P)

1

表示c是一个x

char *(* [10])(int **P)

2

表示x的数组[0~9]

char *(* )(int **P)

3

表示指向x的指针

char *(  )(int **P)

4

表示返回y的函数,且参数是指向指针的指针

char *

5

表示指向char的指针

那么合起来就是c是一个函数指针数组,他的返回类型是char *,参数是int **p

 

以下是来自c专家编程的一个分析声明的程序

 

#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 this;

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

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,"void"))
                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_identifer()
{
        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);
        }
}

main()
{
        read_to_first_identifer();
        deal_with_declarator();
        printf("/n");
        return 0;
}