玩儿转C语言:常见复合类型的声明--注意事项

来源:互联网 发布:高清数字矩阵 编辑:程序博客网 时间:2024/05/18 01:20

1、结构体struct声明注意事项

       结构的定义后面可以直接跟变量名,表示这些变量的类型是这个结构。例如:struct { *** } vol, rate ;这样就定义了两个结构体变量vol和rate。理解:跟基本类型变量的定义“ int number ”本质相同 ,可以认为 struct { *** } 就类似于系统内部类型定义int,只是类型不同而已。

       缺点是:无法利用这个 struct{ *** } 再进行新的变量定义了。

       解决方案是:struct后边增加“结构标签”类似于“ struct tag { *** }  ”,这样以后再定义新变量时,直接用结构体标签“ struct tag vol , xxx,xxx, …… ”。

       能不能再优化一点?

       答案:用typedef进行类型定义,不过这样就无法知道定义的某个变量是不是结构类型了。

       结构中允许存在位段、无名字段以及字对齐所需的填充字段。通过在字段的声明后面加一个冒号以及表示字段位长的整数来实现。

 struct tag  {     unsigned int inactive :1;     unsigned int    :1;          unsigned int test     :6;      short pid_id;    struct tag * next;  }

         位段的类型必须是int、unsigned int或signed int,int位段的值可不可以取负值取决于编译器。而且尽量不要把结构体的声明和结构体变量定义混在一起,这样影响代码阅读。


 2、联合union声明注意事项

       在联合union中,所有的成员都从偏移地址零开始存储,每个成员位置都重叠在一起,在某一时刻只有一个成员真正存储于该地址。

       优点是:可以节省存储空间,对同一个数据可以有多种解释方法。

       缺点是:需要程序员时刻牢记自己存储的数据类型,以便用合理的方式解释数据。
       还有就是可以把同一种数据解释成两种不同的东西,例如结构体和位结构体,尤其是在嵌入式硬件编程和系统通信时使用较多。
例如:

union bit_tag{     uint_8 state;     struct     {  uint_8 bit_1 :4;  uint_8 bit_2 :4;      }BIT;}


3、枚举enum注意事项

       枚举就是简单的把一串名字和一串整型值联系在一起。默认情况下,整型值从0开始,如果对表中某个标识符进行赋值,那么紧接其后的那个标识符就比这个大1,依次类推,直到到达下一个手动赋值的数值开始,继续依照新的基准值开始计数。

       优点:#define定义的名字在编译时就被丢弃了,预处理阶段替换掉了,而枚举名字在调试器中可见,可以在调试时使用。枚举类型定义的变量,在系统中会有类型检查,而#define则没有,所以推荐用枚举。


4、函数声明注意事项

       函数声明要点有3个:函数名称、返回类型和形参类型。声明的好处是在编译时能够对函数调用中的实参和函数声明中的形参之间进行一致性检查。尽管编译器不理睬形参的名称,但最好不要省略形参名,因为它们可以向程序员传递一些有用的信息,例如从" strcpy(char * dst, const char * src) "中可以看到数据流向。


5、数组声明注意事项

       原则上,定义数组时一定要提供数组长度信息,现阶段如果不提供数组长度的详细信息,则编译器会根据初始化的数据内容大小自动识别,进行长度信息初始化。

       对于一位数组,如果有完整的初始化数据,则可以省略数组长度,编译器自动计算数据长度并分配空间;

       对于多维数组,则必须至少提供除了最左边一维之外的其他维的长度,即便是有完整的初始化数据。否则,“完整的初始化数据”只能告诉编译器数组的“总空间”大小,编译器并不能识别不同维度数据单位大小,也就无法进行相对偏移转换,无法实现数据的随机存取。

       上述结论,同样适用于数组声明,尤其是多维数组作为形参传递时,必须至少提供除了最左边一维之外的其他维的长度,在开发实践中初学者容易犯这个错误,就是源于未对问题有深入的理解。    

       总结:对于数组,无论维度大小,定义和声明时最好都带上数组长度信息,便于编译器进行数据截断和处理数据,也便于人工维护。