C语言声明的优先级规则
A 声明从它的名字开始读取,然后按照优先级顺序依次读取
B 优先级从高到底依次是:
B.1 声明中被括号括起来的那部分
B.2 后缀操作符:
括号()表示这是一个函数,而
方括号[]表示这是一个数组
B.3 前缀操作符:星号*表示“指向...的指针”
C 如果const和 volatile 关键字的后面紧跟类型说明符(int long等)它作用域类型说明符,其他情况下,const 和 volatile关键字作用于它左面紧邻的指针星后。
通过上述规则分析下面C语言声明:
char * const *(*next)();
next是一个指针,它指向一个函数,该函数返回一个另一个指针,该指针指向一个类型为char 类型的常量指针
typdef:它为一种类型引入新的名字,并没有创建新的类型
一般情况下,typedef用于简洁地表示指向其他东西的指针。典型的例子是signal()原型的声明
void (*signal(int sig, void (*func)(int)))(int)
signal是一个函数,它返回一个函数指针,这个函数指针指向的函数接受一个int参数并返回void。
可通过typedef做如下改变
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
C语言存在多种名字空间:
标签名(label name)
标签(tag):这个名字空间用于所有的结构、枚举和联合
成员名:每个结构或联合都有自身的名字空间
其他
在同一个名字空间里,任何名字必须具有唯一性,但在不同的名字空间里可以存在相同的名字。由于每个结构或者联合具有自己的名字空间,所以同一个名字可以出现在许多不同的结构内。
typdedef struct my_tag{int i;}mytype;
struct my_tag var1;
mytype var2;
这个typedef声明引入了mytype这个名字作为"struct my_tag{int i;}"的简写方式。但它同时引入了结构标签my_tag,在他前面加个关键字struct可以表示同样的意思。
typedef struct fruit {int weight;}fruit; 语句1
struct veg{int weight;}veg; 语句2
它们代表的意思完全不一样,语句1声明了结构标签fruit和typedef声明的结构类型fruit;实际效果如下
struct fruit mandarin;
fruit mandarin;
语句2声明了结构标签veg和变量veg,只有结构标签能够在以后的声明中使用,如
struct veg potato;
如果试图使用veg cabbage这样的声明,将是一个错误。这有点类似下面的写法:
int i;
i j;
typedef和宏文本替换之间的区别。可以把typedef看成是一种“封装”类型----在声明之后不能再往里面增加别的东西。它和宏的区别体现在两个方面
1、可以用其他类型说明符对宏类型名进行扩展,但对typedef所定义的类型名却不能这样做。
#define peach int
unsigned peach i; 没问题
typedef int peach;
unsigned peach i; 语法错误
2、连续几个变量的声明中,用typedef定义的类型能够保证声明中所有的变量均为同一种类型,而用#define定义的类型无法保证
#define int_ptr int *
int_ptr chalk, cheese;
经过宏扩展
int *chalk, cheese;
chalk是一个指针,cheese是一个整型。
typedef int* int_ptr;
int_ptr chalk,cheese;
chalk,cheese都为整型指针
枚举类型
enum sizes { small = 7, medium, large = 10, humungous};
缺省情况下,整型值是从零开始。如果对列表中的某个标识符进行了赋值,那么紧接其后的那个标识符的值就比所赋的值大1,然后类推
枚举中的成员可以当做宏一样直接使用,相比宏定义枚举具有一个优点:#define定义的名字一般在编译时被丢弃,而枚举名字则通常一直在调试器中可见,可以在调试代码时使用它们。