程序比程序员更理解c语言! cdecl程序(分析c语言的声明

c语言的声明有时侯是很复杂的;比如int (*a[5])(int); 再比如:int*((*p)(int))(int);你能说明白它们的意思吗?

像这样的声明很容易把一般的程序员弄蒙逼的。

cdecl是一个分析这种声明的程序,输入声明形式,用英语输出其描述。

一个在线的cdecl.

我们也可以自己编写分析程序。编写一个这样的分析程序,很有助于帮助我们理解c语言的声明。

下面是照着《c专家编程》敲的cdecl程序。

/*
 * =====================================================================================
 *
 *       Filename:  cdecl.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2012年02月28日 21时54分11秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  MaZheng (blog.csdn.net/mazheng1989), mazheng19891019@gmail.com
 *        Company:  Dalian University Of Technology
 *
 * =====================================================================================
 */


#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,"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)/*读取下一个标记到 this*/
{
	char *p=this.string;
	/*略过空白字符*/
	while((*p=getchar())==' ');

	if(isalnum(*p))
	{
		/*读入的标识符以A—Z,0-9开头*/
		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 ;
}
void read_to_first_identifier()
{
	gettoken();
	while(this.type!=IDENTIFIER)
	{
		push(this);
		gettoken();
	}
	printf("%s is ",this.string);
	gettoken();
}
void deal_with_arrays()
{
	while(this.type=='[')
	{
		printf("array ");
		gettoken();/*数字或']'*/
		if(isdigit(this.string[0]))
		{
			int temp;
			sscanf(this.string,"%d",&temp);
			printf("0..%d ",temp-1);
			gettoken();/*读取']'*/
		}
		gettoken();/*读取']'之后的再一个标记*/
		printf("of ");
	}
}
void deal_with_function_args(){
	/*处理函数参数*/
	while(this.type!=')')
	{
		gettoken();
	}
	gettoken();
	printf("function returning ");
}
void deal_with_pointers(){
	while(stack[top].type=='*')
	{
		printf("%s ",pop.string);
	}
}
void deal_with_declarator()
{
	/*处理标识符之后可能存在的数组/函数*/
	switch(this.type)
	{
		case '[':
			deal_with_arrays();
				 break;
		case '(':
				 deal_with_function_args();
				 break;
	}
	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;
}
编译:gcc cdecl.c -o cdecl

输入: int *((*p)(int))(int)
输出:p is pointer to function returning function returning pointer to int


没有更多推荐了,返回首页