自定义类型:结构体,枚举,联合
来源:互联网 发布:centos升级内核 编辑:程序博客网 时间:2024/05/20 23:31
结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。
先来声明一个结构体:
struct tag{ member-list;}variable-list;
在声明结构的时候,可以不完全声明:
struct { int a; int b; char c;}x;
struct { int a; float b; char c;}a[15],*p;
下面这个结构体声明就是错误的声明:
struct { int a; int b; char c;};
举一个例子来说明结构体的使用:
struct Stu{ char name[20]; int age; char sex[5]; char id[20];}n = { "zhangs", 20 , "male", "153515" };void main(){ printf("%s,%d,%s,%s", n.name, n.age,n.sex, n.id); system("pause");}
“n = { “zhangs”, 20 , “male”, “153515” }; ” 这一步初始化了结构体变量,还可以这样初始化结构体变量:
struct Stu{ char name[20]; int age; char sex[5]; char id[20];};struct Stu s = {"zhangs", 20 , "male", "153515"};
在输出结果时我们用了(.)符号完成了对结构体的访问,(.)操作符仅接受两个操作数。
现在已经掌握了结构体的基本使用,接下来我们讨论如何计算结构体的大小:
计算结构体的大小时要考虑到内存对齐问题。
结构体的内存对齐规则:
- 第一个成员在与结构体变量偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的值为8
Linux中的默认值为4 - 结构体总大小为最大对齐数(每个成员变量除了第一个成员都有一个对齐
数)的整数倍。 - 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍
处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整
数倍。
struct S3{ double d; char c; int i;};//大小为16,最大对齐数为4struct S4{ char c1; struct S3 s3; double d;};//大小为32,最大对齐数8struct S5{ struct S4 s4; int c3;};void main(){ printf("%d\n", sizeof(struct S3)); printf("%d\n", sizeof(struct S4)); printf("%d", sizeof(struct S5)); system("pause");}
先来计算S3的大小,double和char 的大小为9,而最大对齐数int为4,(第一个成员也有对齐数,但是不需要对齐,不考虑对齐数),结构体大小要为最大对齐数整数倍,所以sizeof(S3) = 8+1+3+4=16.
同理,S4大小为1+16+7+8=32.
S5大小是32+4吗?
答案是:不是。
不是说不考虑第一个成员对齐数吗?
这是因为结构体S5中嵌套了结构体S4,结构体S5的最大对齐数就是 结构体内的结构体S4 的最大对齐数8,36必须对齐到最大对齐的整数倍40,所以结果就是40。
为什么要存在内存对齐?
1. 平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能
在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2. 性能原因:
数据结构(尤其是栈)应该尽可能地在自然边界上对齐。
原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的
内存访问仅需要一次访问 。
位段
C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域”(bitfield)。利用位段能够用较少的位数存储数据。
位段与结构体的不同:
1.位段的成员必须是 int、unsigned int 或signed int 。
2.位段的成员名后边有一个冒号和一个数字。
比如:
struct A{ int _a:2; int _b:5; int _c:10; int _d:30;};
那么位段的大小应该如何计算:
在32位平台下位段的最大数目为32,所以下例中int可存放 最大数目为32。
struct A{ int _a:2; int _b:5; int _c:10; int _d:30;};void main(){ printf("%d", sizeof(struct A)); system("pause");}
位段不会像结构体那样浪费空间,它会连续存放,如果剩余空间不够存放,将开辟一个新的int来存放。
所以答案是8.
与结构相比,位段可以达到同样的效果,但是位段可以节省空间,但是有跨平台的问题存在(位段中最大数目会因平台不同而不同)。
枚举
先定义一个枚举
enum Day//星期{ Mon, Tues, Wed, Thur, Fri, Sat, Sun};
{}中的内容是枚举类型的可能取值,也叫 枚举常量 。这些可能取值都是有值的,默认从0
开始,一次递增1,当然在定义的时候也可以赋初值。
我们可以使用 #define 定义常量,为什么非要使用枚举?
枚举的优点:
1. 增加代码的可读性和可维护性
2. 很#define定义的标识符比较枚举有类型检查,更加严谨。
3. 防止了命名污染(封装)
4.便于调试
5.使用方便,一次可以定义多个常量。
联合体
联合也是一种特殊的自定义类型
这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合
也叫共用体)。
声明一个联合体:
union Un{ char c; int i;};
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成
员的大小(因为联合至少得有能力保存最大的那个成员)。那么如何计算联合体的大小?
联合的大小至少是最大成员的大小。
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数
倍。
union Un1{ char c[5]; int i;};union Un2{ short c[7]; int i;};void main(){ printf("%d\n", sizeof(union Un1)); printf("%d\n", sizeof(union Un2)); system("pause");}
在Un1中,char的大小为5,联合体大小要为最大对齐数的整数倍,所以Un1大小为8.
同理,Un2中,short大小为14,联合体大小为16.
介绍就到这里,这些自定义类型要经常使用,使代码更加简洁,易读。
- 自定义类型:结构体、枚举、联合
- 自定义类型:结构体,枚举,联合
- 自定义类型:结构体,枚举,联合
- 自定义类型:结构体,枚举,联合
- 自定义类型(结构体、位段、枚举和联合)
- 自定义类型——结构体、枚举、联合
- 自定义类型:结构体,位段,枚举,联合
- 自定义类型(结构体,枚举,联合,位段)
- 自定义类型(结构体,位段,枚举,联合)总结
- 自定义类型——结构体,枚举,联合
- Pace 12 (自定义类型:结构体 位段 枚举 联合)
- 结构体、联合、枚举
- 结构体,枚举,联合
- 自定义类型部分知识写一篇博客。 知识点: >结构体类型创建 >结构体初始化 >结构体内存对齐 >位段,位段计算机大小。 >枚举+联合。
- 自定义类型:结构体,枚举,联合体
- 自定义类型:结构体,枚举,联合体
- 自定义类型---->结构体,枚举,联合体
- 联合 枚举和结构体
- [BZOJ]3262: 陌上花开 CDQ分治+树状数组
- 写冒泡排序可以排序多个字符串
- css中单位px、pt、em和rem的区别
- cookie的属性和属性的作用
- Valid Palindrome II
- 自定义类型:结构体,枚举,联合
- LeetCode 566.Reshape the Matrix
- 如何在Ubuntu Linux中查找您的IP地址 [译]
- 关于奶牛art1003的题解
- Unity3d Dotween插件的简单介绍及示例代码
- 网络通信
- HTTP协议_状态码和请求方法
- FRAMEWORK 添加新的接口
- CSS实现单行、多行文本溢出显示省略号(…)