C中的结构,联合,枚举(持续总结中...)

1.结构

1.结构声明和定义及使用

声明两种方法:

struct x1{...}; 和 typedef  struct{...}   x2;  //x1表示标签,实际上可以把struct和x1看成一个整体,表示这是一个结构标签,相当于整型类型
第一个是声明一个结构标签,第二个是声明类型定义,也是类型重命名。
主要区别 :第二个比较抽象,用户不必知道它是一个结构,声明它的实例是不需要使用struct关键字

定义

定义方法一:
struct      x1      x1;
struct      x1      y[20] , *z ;
定义结构体,标签x1和类型定义使用同样的名称是合法的,因为它们处于独立的命名空间。

定义方法二:
typedef structx3{...}x3 ; (声明同时定义)

定义方法三:
x2      x;
x2      y[20] , *z ;


C和C++使用结构的区别:

1,C不能用结构标签自动生成类型定义名。如struct   x{...};   x   thestruct  ;
2,C模拟C++继承等面向对象程序设计特性的好方法是:把函数指针直接加入结构中;

成员:
1,结构可以包含指向自己的指针,但是如果使用typedef声明或定义的结构,可能产生问题。
2,允许结构体组后一个域省略数组大小,柔性数组。

结构体使用之常见错误:

1.
extern int f(struct x *p);


结构体使用之疑惑:

1,不能用内建的 “==” 和“!=”操作符比较结构
1)结构体成员涉及内存对齐,对齐时填补空位的是随机数据,因此不能按字节比较
2)按位域比较的方式,则在处理大结构时可能需要接受大量重复代码。
3)任何编译器生成的比较代码都不能期望在所有情况下都正确比较指针域,一般希望使用strcmp而不是“ == ”。
      所以,比较两个结构,必须自己写函数按域比较

2,结构传递和返回的实现
为避免结构作为函数参数传递时,把整个结构压栈而浪费空间,常传递一个指向结构的指针。并且对结构体,编译器将保留一个局部副本。
3,确定域在结构中的字节偏移量,并用名字访问结构中的域
1,可以用ANSI C在<stddef.h>中定义的offsetof( structs , f )宏计算。
2,自己实现方法:
#define offsetof(type,f)  ((size_t)((char *)&((type *)0)->f -(char *)(type *)0))
// 对类型转换后的空指针(type *)0的减法是为了确保即使空指针的内部表示不是0的时候,也能正确计算出偏移。
//转成(char *)指针确保计算出的偏移是字节偏移。
1)创建一个表保存名称和域偏移量。如结构a的b域(int型)的偏移量:
offsetb = offsetof( struct  a , b )
2)   定义structp是结构实例的指针,b的值value 等于绝对地址+偏移量
*(int *)((char *)structp + offsetb)



2.结构填充

为了能高效访问内存,编译器会要求内存对齐。编译器可能提供某种扩展用于控制结构的填充,如#pragma,但是没有标准方法。
为了节省空间,可以把结构中的域从大到小的顺序排序。数组成员应该根据它的元素类型大小而不是整个数组的大小。

2.联合

联合:本质是一个成员的相互重叠的结构,某一时刻只能用一个成员,也可以从一个成员写入,从另一个成员读出,来检查某种类型的二进制模式。
联合的大小:最大成员的大小,需要内存对齐。
  初始化:C99引入“指定初始式”,可以初始化任意成员。

3.枚举

枚举为整型,枚举常量为int型。
优点:
1,自动赋值
2,调试器在检验枚举变量时,可以显示符号值;
3,它们服从数据块作用域规则。(当枚举变量被任意地和其他类型混用,编译器认为是坏风格而可产生非致命警告)

缺点:
无法控制枚举变量的大小。

4.位域

 表示该域按位计量的准确大小,只适用于结构和联合的成员,不适合其他变量。
struct record{
	char *name;
	int refcount : 4;
	unsigned dirty : 1;
}
 作用:
 1,节省存储空间,特别是对于有很多二进制标志和其他小成员的结构;
 2, 满足外部要求的存储布局。
 位域在机器上的分配可能是从左到右,或从右到左。





























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值