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 ;
}