C 语言复杂声明
对C复杂声明的理解,到现在还是不行,这是从K&R 第二版中找到的一个程序, 可以加强理解:
dcl.h
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h>
2 #include <string.h>
3 #include <ctype.h>
4
5 #define MAXTOKEN 100
6 #define BUFSIZE 100
7
8 enum { NAME, PARENS, BRACKETS };
9
10 char buf[BUFSIZE];
11 int bufp = 0;
12 int getch(void);
13 void ungetch(int c);
14
15 int tokentype;
16 char token[MAXTOKEN];
17 char name[MAXTOKEN];
18 char datatype[MAXTOKEN];
19 char out[1000];
20
21 void dcl(void);
22 void dirdcl(void);
23 int gettoken(void);
2 #include <string.h>
3 #include <ctype.h>
4
5 #define MAXTOKEN 100
6 #define BUFSIZE 100
7
8 enum { NAME, PARENS, BRACKETS };
9
10 char buf[BUFSIZE];
11 int bufp = 0;
12 int getch(void);
13 void ungetch(int c);
14
15 int tokentype;
16 char token[MAXTOKEN];
17 char name[MAXTOKEN];
18 char datatype[MAXTOKEN];
19 char out[1000];
20
21 void dcl(void);
22 void dirdcl(void);
23 int gettoken(void);
dcl.c
1 #include "dcl.h"
2
3 void dcl(void)
4 {
5 int ns;
6
7 for(ns = 0; gettoken() == '*'; )
8 ns++;
9 dirdcl();
10 while(ns-- > 0)
11 strcat(out, " pointer to");
12 }
13
14 void dirdcl(void)
15 {
16 int type;
17
18 if( tokentype == '(') {
19 dcl();
20 if(tokentype != ')')
21 printf("error: missing )\n");
22 } else if (tokentype == NAME) {
23 strcpy(name, token);
24 } else {
25 printf("error: expected name or (dcl)\n");
26 }
27 while((type = gettoken()) == PARENS || type == BRACKETS)
28 if(type == PARENS) {
29 strcat(out, " function returning");
30 } else {
31 strcat(out, " array");
32 strcat(out, token);
33 strcat(out, " of");
34 }
35 }
36
37 int gettoken(void)
38 {
39 int c;
40 char *p = token;
41
42 while((c = getch()) == ' ' || c == '\t')
43 ;
44 if(c == '(') {
45 if((c = getch()) == ')') {
46 strcpy(token, "()");
47 return tokentype = PARENS;
48 } else {
49 ungetch(c);
50 return tokentype = '(';
51 }
52 } else if (c == '[') {
53 for(*p++ = c; (*p++ = getch()) != ']'; )
54 ;
55 *p = '\0';
56 return tokentype = BRACKETS;
57 } else if(isalpha(c)) {
58 for(*p++ = c; isalpha(c = getch()); )
59 *p++ = c;
60 *p = '\0';
61 ungetch(c);
62 return tokentype = NAME;
63 } else
64 return tokentype = c;
65 }
66
67 int getch(void)
68 {
69 return (bufp > 0) ? buf[--bufp] : getchar();
70 }
71 void ungetch(int c)
72 {
73 if(bufp >= BUFSIZE)
74 printf("ungetch: too many characters\n");
75 else
76 buf[bufp++] = c;
77 }
78
79 int main(void)
80 {
81 while(gettoken() != EOF) {
82 strcpy(datatype, token);
83 out[0] = '\0';
84 dcl();
85 if(tokentype != '\n')
86 printf("syntax error\n");
87 printf("%s: %s %s\n", name, out, datatype);
88 }
89 return 0;
90 }
2
3 void dcl(void)
4 {
5 int ns;
6
7 for(ns = 0; gettoken() == '*'; )
8 ns++;
9 dirdcl();
10 while(ns-- > 0)
11 strcat(out, " pointer to");
12 }
13
14 void dirdcl(void)
15 {
16 int type;
17
18 if( tokentype == '(') {
19 dcl();
20 if(tokentype != ')')
21 printf("error: missing )\n");
22 } else if (tokentype == NAME) {
23 strcpy(name, token);
24 } else {
25 printf("error: expected name or (dcl)\n");
26 }
27 while((type = gettoken()) == PARENS || type == BRACKETS)
28 if(type == PARENS) {
29 strcat(out, " function returning");
30 } else {
31 strcat(out, " array");
32 strcat(out, token);
33 strcat(out, " of");
34 }
35 }
36
37 int gettoken(void)
38 {
39 int c;
40 char *p = token;
41
42 while((c = getch()) == ' ' || c == '\t')
43 ;
44 if(c == '(') {
45 if((c = getch()) == ')') {
46 strcpy(token, "()");
47 return tokentype = PARENS;
48 } else {
49 ungetch(c);
50 return tokentype = '(';
51 }
52 } else if (c == '[') {
53 for(*p++ = c; (*p++ = getch()) != ']'; )
54 ;
55 *p = '\0';
56 return tokentype = BRACKETS;
57 } else if(isalpha(c)) {
58 for(*p++ = c; isalpha(c = getch()); )
59 *p++ = c;
60 *p = '\0';
61 ungetch(c);
62 return tokentype = NAME;
63 } else
64 return tokentype = c;
65 }
66
67 int getch(void)
68 {
69 return (bufp > 0) ? buf[--bufp] : getchar();
70 }
71 void ungetch(int c)
72 {
73 if(bufp >= BUFSIZE)
74 printf("ungetch: too many characters\n");
75 else
76 buf[bufp++] = c;
77 }
78
79 int main(void)
80 {
81 while(gettoken() != EOF) {
82 strcpy(datatype, token);
83 out[0] = '\0';
84 dcl();
85 if(tokentype != '\n')
86 printf("syntax error\n");
87 printf("%s: %s %s\n", name, out, datatype);
88 }
89 return 0;
90 }