C语言的声明存在的最大问题是你无法以一种人们所习惯的自然方式从左向右阅读一个声明,在ANSI C引入const和volatile关键字后,情况就更糟糕了。由于这些关键字只能出现在声明中(而不是使用中),这使得现今声明形式和使用形式能完全对得上号的例子越来越少。例如:
const int *grape;
int const *grape;
// 上述二者是等价的都表示指向常整型的指针
int * const grape_jelly; // 其表示指针是只读的
基于阅读方便,不要将结构的声明和结构类型变量的定义放在一起,应该采用分离的方式,如:
struct veg
{
int weight;
double price;
}
struct veg onion, radish, turnip;
联合既有一些优点,也有一些缺点。它的缺点是那些所谓的优点其实并不怎么出色,它的优点是外观同结构一样,只是用union替代了struct。
联合一般作为大型结构的一部分存在的。联合一般被用来节省空间,因为有些数据项是不可能同时出现的,如果同时存储它们,显然颇为浪费。
对于像C这样的弱类型语言,很少有什么事是只能通过枚举而不能用#define解决的。
枚举的唯一优点是,#define定义的名字在编译时会被丢弃,而枚举名字则能在调试器中可见。
C语言的优先级规则:
(1)声明从它的名字开始读取,然后按照优先级顺序依次读取。
(2)优先级从高到低依次是:①声明中被括号括起来的部分,②后缀操作符,()表示这是一个函数,[]表示这是一个数组;③前缀操作符,*表示这是指向…的指针。
(3)如果const和volatile关键字的后面紧跟类型说明符,则它作用于类型说明符。在其他情况下,关键字作用于它左边紧邻的指针星号。
不要在一个typedef 中放入几个声明器。不要把typedef嵌入到声明的中间部分。
不要为了方便对结构使用typedef,这样做的唯一好处是能使你不必书写struct关键字,但这个关键字可以向你提示一些信息,不应该被省掉。
typedef应该用在:
(1)数组、结构、指针、以及函数的组合类型;
(2)可移植类型。比如当你需要一种至少20bit的类型时,可以对它进行typedef操作。这样当把代码移植到不同平台时,只需修改typedef就可以了;
(3)typedef可以为后面的强制类型转换提供一个简单的名字,如:
typedef int (*ptr_to_int_fun)(void);
char *p;
... = (ptr_to_int_fun)p;
strcmp()函数用于比较两个字符串,它所存在的其中一个问题是,当两个字符串相等时函数的返回值为0,所以在实际使用中不得不对齐取反,以得到想要的结果。可以使用宏定义:
#define STRCMP(a, R, b) (strcmp(a, b) R 0)
于是就可以按照正常思路编写代码:
if (STRCMP(S, ==, 'volatile'))