1.只有编译器才会喜欢的语法
“声明的形式和使用的形式相似”这种用法可能是C语言的独创,其它语言并没有采取这种方法。C语言的声明所存在的最大问题是你无法以一种人们所习惯的自然方式从左向右阅读一个声明,在ANSI C引入volatile和const关键字后,情况就更糟糕。
2.声明是如何形成的
声明器——它是所有声明的核心。简单的说,声明器就是标识符以及与它组合在一起的任何指针、函数括号、数组下标等。
函数的返回值不能是一个函数,所以像foo()()这样是非法的;函数的返回值不能是一个数组,所以像foo()[]这样是非法的;数组里面不能有函数,所以像foo[]()这样是非法的。但像下面这样是合法的:
函数的返回值允许是一个函数指针,如:int(*fun())();函数的返回值允许是一个指向数组的指针,如:int(*foo())[];数组里面允许有函数指针,如:int(*foo[])();数组里面允许有其它数组,所以经常可以看到int foo[][]。
2.1 关于结构
struct结构体
struct s_tag {int a[100];};
struct s_tag orange,lime,lemon;
struct s_tag twofold(struct s_tag s){
int j;
for(j=0;j<100;j++)
s.a[j]*=2;
return s;
}
main(){
int i;
for(i=0;i<100;i++)
lime.a[i]=1;
lemon=twofold(lime);
orange=lemon;//给整个结构赋值
}
2.2 关于联合
union secondary{
char fur;
short num;
};
uno=ion bits32_tag{
int whole; //一个32位的值
struct{char c0,c1,c2,c3}byte; //4个8位的字节
}value;
2.3 关于枚举
enum sizes{
small=7,
medium,
large=10,
humungous,
};
3.优先级规则
A 声明从它的名字开始读取,然后按照优先级顺序依次读取
B 优先级从高到底依次是:
B.1 声明中被括号括起来的部分
B.2 后缀操作符:
括号()表示这是一个函数,而方括号[]表示这是一个数组
B.3 前缀操作符:*表示“指向...的指针”
C 如果const和volatile关键字的后面紧跟类型说明符(如int,long等),那么它作用于类型说明符,在其它情
况下,const和volatile关键字作用于它左边紧邻的指针*号.
4.通过图表分析C语言的声明
分析与匹配。
5.typedef可以成为你的朋友
typedef它为一种类型引入新的名字,而不是为变量分配空间。
操作声明器的一些提示:不要在一个typedef中放入几个声明器,如下所示:
typedef int *ptr,(*fun)(),arr[5];
千万不要把typedef嵌到声明的中间部分,如下所示:
unsigned const long typedef int volatile *kumquat;
6.typedef int x[10]和#define x int[10]的区别
首先,可以用其它类型说明符对宏类型名进行扩展,但对typedef所定义的类型名却不能这样做:
#define peach int;
unsigned peach i;//没问题
typedef int banana;
unsigned banana i;//错误,非法
其次,在连续几个变量的声明中,用typedef定义的类型能够保证声明中所有的变量均为同一种类型,而用
#define定义的类型则无法保证:
#define int_ptr int *;
int_ptr chalk,cheese; //等价int *chalk,cheese;
typedef char * char_ptr;
char_ptr bentley,Rolls;//等价 cahr *bentley, char *Rolls;
7.typedef struct foo{...foo;}的含义
C语言存在多种名字空间:标签名;标签;成员名;其它;
struct vnode{
long v_flag;
long v_usecount;
struct vnode *v_freef;
struct vnodeops *v_op;
};
由于在不同的名字空间内使用同一个名字是合法的
struct foo{int foo;}foo;
操作typedef的提示:不要为了方便起见对结构使用typedef;应该用在数组、结构、指针以及函数的组合类型,可移植类型;可以为后面的强制类型转换提供一个简单的名字。