分析C语言的声明

原创 2007年09月14日 13:50:00

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

C编译器剖析_3.3 语法分析_C语言的外部声明(2)

在上一小节中,我们讨论了C标准文法的“外部声明ExternalDeclaration”,介绍了“声明Declaration”和“函数定义FunctionDefintion”这两类外部声明,分别举了以下...

分析C语言的声明的优先级

C语言的声明是C语言区别于其他语言的一大亮点,本文主要讲解的是C声明的优先级规则。

Chapter_03 分析C语言的声明

3.1 只有编译器才会喜欢的语法 C语言的声明语法(声明模型)很晦涩,容易成为程序员的障碍,正是由于在组合类型方面的笨拙行为,C语言显得很复杂。 造成这种情况的原因是因为“类型模型(type mo...

C编译器剖析_3.3 语法分析_C语言的外部声明(1)

3.3  C语言的外部声明_ExternalDeclaration     在分析完表达式和语句之后,《K&R》附录中关于标准C的6页文法,我们就已经差不多已经理解了一半,另外的3页文法基本上都是关...

C语言中const分析(未知大小的全局变量数组声明出错)

一、const常量分析 1、 #include  const bufsize = 100; char buf[bufsize]; int main() { return 0; } 编...

c专家编程笔记之第三章分析c语言的声明

1:“声明的形式和使用的形式相似” 例如:一个int类型的指针数组被声明为 int *p[3],并以*p[i]这样的表达式引用或者使用指针所指向的int数据 #include #include...

《C专家编程》学习笔记(分析C语言的声明)

一、C语言声明的语法有时会带来严重的问题 1、

【C专家编程】第3章 分析C语言的声明

第3章 分析C语言的声明 声明 C语言中,对象的声明形式域它的使用形式尽可能相似 const int * ptr与int const * ptr相同 合法的声明存在限制条件 l  函数的返回值不能是一...

C语言中声明和定义的区别——分析extern关键词。

一直很迷惑C语言中的声明和定义的有些实践中的用法,说迷惑实践是因为声明和定义的概念上的区别是很明确的。 定义和声明的区别(主要针对变量): 定义是要为变量分配存储空间,还可以在定义的时候为变量指定...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)