第3章 分析C语言的声明
●只有编译器才会喜欢的语法
C语言的声明所存在的最大的问题是你无法以一种人们所习惯的自然的方式从左自右阅读一个声明,在ANSI C引入volatile和const关键字后,情况就更糟糕了。由于这些关键字只能出现在声明中(而不是在使用中),这就使得声明形式和使用形式不能完全对得上号。
●声明是如何形成的
声明器-它是所有声明的核心。简单地说,声明器就是标识符以及与它组合在一起的任何指针、函数括号、数组下标等。
声明器:零个或多个指针+有且只有一个直接声明器+初始化内容
声明:至少一个类型说明符(类型说明符、存储类型、类型限定符)+有且只有一个声明器+零个或更多声明器+一个分号
关于结构
结构就是一种把一些数据项组合在一起的数据结构,其它编程语言把它称为记录。
结构的通常形式是:
struct 结构标签(可选) {
类型1 标识符1;
类型2 标识符2;
…
类型N 标识符N;
}变量定义(可选);
结构中也允许存在位段、无名字段以及对齐所需的填充字段。这些都是通过在字段的声明后面加上一个冒号以及一个表示字段位长的整数来实现的。
不要把结构变量的声明和定义混合在一起。
关于联合
联合在许多其它语言中被称为变体记录。它的外表与结构相似,但在内存布局上存在关键性的区别。在结构中,每个成员依次存储,而在联合中,所有的成员都从偏移地址零开始存储。这样,每个成员的位置都重叠在一起;在某一时刻,只有一个成员真正存储于该地址。
联合的一般形式是:
union 结构标签(可选) {
类型1 标识符1;
类型2 标识符2;
…
类型N 标识符N;
}变量定义(可选);
联合一般用来节省空间,也可以把同一数据解释成两种不同的东西。在实际工作中,结构的应用远远多于联合。
关于枚举
枚举通过一种简单的途径,把一串名字与一串整型值联系在一起。
枚举的一般形式是:
enum 可选标签 {
内容…
}可选变量定义;
缺省情况下,整型值从零开始。如果对列表中的某个标识符进行了赋值,那么紧接其后的标识符的值就比所赋的值大于1,然后类推。
枚举有一个优点:#define定义的名字一般会在编译时被丢弃,而枚举名字则不会。
●优先级规则
理解C语言声明的优先级规则
A 声明从它的名字开始读取,然后按照优先级顺序依次读取。
B 优先级从高到低依次是:
1、声明中被括号括起来的那部分
2、后缀操作符:
括号()表示这是一个函数,而方括号[]表示这是一个数组。
3、前缀操作符:星号*表示“指向…的指针”。
C 如果const和(或)volatile关键字的后面紧跟类型说明符(如int、long等),那么它的作用于类型说明符。在其它情况下,const和(或)volatile关键字作用于它左边紧邻的指针星号。
●通过图表分析C语言的声明
●typedef可以成为你的朋友
typedef为一种类型引入新的名字,而不是为变量分配空间。
typedef为数据类型创建别名,而不是创建新的数据类型,可以对任何数据类型进行typedef声明。
不要在一个typedef中放入几个声明器,不要把typedef嵌入到声明的中间部分。在同一代码块中,typedef引入的名字不能与其它标识符同名。
typedef和宏文本替换关键性的区别:
1、可以用其它类型说明符对宏类型名进行扩展,但对typedef所定义的类型名却不能这样做。
2、在连续几个变量的声明中,用typedef定义的类型能够保证声明中所有的变量均为同一种类型,而用#define定义的类型则无法保证。
C语言存在多个名字空间,在同一个名字空间里,任何名字必须具有唯一性,但在不同的名字空间内可以存在相同的名字。
不要为了方便起见对结构使用typedef,typedef应该用在:
1、数组、结构、指针以及函数的组合类型。
2、可移植类型。
3、为强制类型转换提供一个简单的名字。
应该始终在结构定义中使用结构标签,这样可以使代码更加清晰。
当有两个不同的东西时,比较好的原则就是用不同的名字来称呼它们,这样做减少了混淆的危险。
文章评论(0条评论)
登录后参与讨论