关闭

分析C语言的声明

680人阅读 评论(0) 收藏 举报

C语言的声明是让初学者最为头疼的地方之一,本文提供一种理解C语言声明的方法之一,仅供参考。

要理解一个声明,必须要懂得其中的优先级规则。以下提供一个优先级规则
A 声明从它的名字开始读取,然后按照优先级顺序依次读取
B 优先级从高到低依次是:
    B 1声明中被括号括起来的那部分
    B 2后缀操作符:括号()表示这是一个函数,而方括号[]表示这是一个数组
    B 3前缀操作符:星号*表示"指向...的指针"
C 如果const和(或) volatile关键字的后面紧跟类型说明符(如int,long等),那么它作用于类型说明符。在其它情况下,const和(或) volatile关键字作用于它左边紧邻的指针星号

以下是一个例子:

char * const *(*next)();

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

将以上分析结果加以概括,这个声明表示"next是一个指针,它指向一个函数,该函数返回另一个指针,该指针指向一个类型为char的常量指针",大功告成。

另外附一个将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 thistoken;

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

/*推断标识符类型*/
enum type_tag classify_string(void)
{
 char *s=thistoken.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,"enum"))
  return TYPE;
 if(!strcmp(s,"union"))
  return TYPE;
 return IDENTIFIER;
}

/*读取下一个标记到"thistoken"*/
void gettoken(void)
{
 char *p=thistoken.string;
 /*略过空白字符*/
 while((*p=getchar())==' ')
  ;
 if(isalnum(*p)){
  while(isalnum(*++p=getchar()))
   ;
  ungetc(*p,stdin);
  *p='/0';
  thistoken.type=classify_string();
  return;
 }

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

 thistoken.string[1]='/0';
 thistoken.type=*p;
 return;
}

/*理解所有分析过程的代码段*/
void read_to_first_identifier(){
 gettoken();
 while(thistoken.type!=IDENTIFIER){
  push(thistoken);
  gettoken();
 }
 printf("%s is ",thistoken.string);
 gettoken();
}

void deal_with_arrays(){
 while(thistoken.type=='['){
  printf("array ");
  gettoken();
  /*数字或中括号*/
  if(isdigit(thistoken.string[0])){
   printf("0..%d ",atoi(thistoken.string)-1);
   gettoken(); /*读取']' */
  }
  gettoken();  /*读取']'之后的再一个标记*/
  printf("of ");
 }
}

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

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

void deal_with_declarator(){
 /*处理标识符之后可能存在的数组/函数*/
 switch(thistoken.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;
}

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:25413次
    • 积分:438
    • 等级:
    • 排名:千里之外
    • 原创:18篇
    • 转载:1篇
    • 译文:0篇
    • 评论:6条
    最新评论