祁阳网站设计,网页设计软件vscode,济南烨铭网站建设,吴江住房和城乡建设部网站前言#xff1a;小伙伴们又见面啦#xff0c;今天这篇文章#xff0c;我们来谈谈几种自定义数据类型。 目录
一.都有哪些自定义数据类型
二.结构体
结构体内存对齐
1.如何对齐 2.为什么要对齐
3.节省空间和提升效率的方法
#xff08;1#xff09;让占用空间小的成员…前言小伙伴们又见面啦今天这篇文章我们来谈谈几种自定义数据类型。 目录
一.都有哪些自定义数据类型
二.结构体
结构体内存对齐
1.如何对齐 2.为什么要对齐
3.节省空间和提升效率的方法
1让占用空间小的成员尽量集中在一起
2修改默认对齐数
三.位段 1.什么是位段
2.位段的的内存分配 3.位段的跨平台问题
四.枚举
1.枚举类型的定义
2.枚举的优点
五.联合体
1.联合体的定义 2.联合体的使用 3.联合体大小的计算
六.总结 一.都有哪些自定义数据类型
我们在C语言的基础中已经了解到了结构体是一种对多种数据集中管理的一种自定义数据类型。
除此之外我们还有另外三种-
位段枚举联合
接下面我们就开始对这四种数据类型逐一展开讲解。 二.结构体
在我们前边的文章《C语言基础之——结构体》中我们已经对结构体展开了细致的讲解所以在这篇文章中我们不再重复讲解。
那么在这篇文章中我们来谈谈结构体类型的大小。
我们知道任何一种数据类型都有它所占用的内存大小但是结构体类型却是多种数据类型的整合。
那小伙伴们是否知道结构体类型该如何计算大小呢
来看例子
#includestdio.h
struct Str1
{char a;char b;int c;
};
struct Str2
{char a;int b;char c;
};
int main()
{int num1 sizeof(struct Str1);int num2 sizeof(struct Str2);printf(%d\n, num1);printf(%d\n, num2);
}
小伙伴们可以猜一猜Str1 和 Str2的内存大小会是多少呢
有的小伙伴可能会说啊都是两个char类型和一个int类型那大小不就是6呗。
那到底是不是6呢我们来看结果 哇塞天差地别不仅不是6而且两个数还不一样。 这是为什么呢
事实上对于结构体有结构体内存对齐这样一个概念。 结构体内存对齐
1.如何对齐 我们先来看对齐的规则 1.第一个成员放在与结构体变量偏移量为0的地址处。 2.其他成员变量要对齐到某个数字对齐数的整数倍的地址处。 对齐数 编译器默认的一个对齐数与该成员大小的较小值。 博主所使用的VS2019的默认对齐数为8Linux中没有默认对齐数对齐数就是成员变量本身的大小 3.结构体总大小为最大对齐数每个成员变量都有一个对齐数的整数倍。 4.如果出现嵌套结构体的情况嵌套的结构体对齐到自己的最大对齐数的整数倍处结构体的整体大小就是所有最大对齐数含嵌套结构体的对齐数的整数倍。 什么意思呢下面我们根据例子来具体讲解 struct Str1 { char a; char b; int c; }; 首先来看这个结构体它的第一个成员变量a为char型 大小为1个字节放在结构体变量偏移量为0的地址处即从0开始存放。
然后第二个成员变量b也是char类型大小为1个字节从第二个成员变量开始我们要根据最大对齐数进行对齐将1与8相比肯定是1较小所以对齐数为1所谓对齐数就是这个成员变量所存放的空间的前边所占用的空间个数需要是对齐数的整数倍要对齐到1的整数倍的位置我们现在只占用了一个字节1是1的整数倍数那自然就是从第二个字节开始存放占用一个字节。
最后来看第三个成员变量c为int类型大小为4个字节则其对齐数为4那么我们要对齐到4的整数倍的位置但是现在我们只有两个字节的位置被占用2不是4的整数倍数所以我们还需要浪费两个字节来实现对齐到4的倍数的位置所以要从标号为4的位置存放四个字节。 这样一来我们就得到了我们的结果8个字节。
下边我们继续来看一个例子 struct Str2 { char a; int b; char c; }; 第一个为char型放在0处。
第二个为int型对齐数为4,现在只占用了一个字节不是4的整数倍所以要浪费3个字节从标号为4的位置开始占用四个字节。
第三个为char型对齐数为1,8是1的整数倍所以直接从标号为8的位置开始占用一个字节。 这个时候出问题了这不是才9个字节吗那结果为什么是12个字节呢
这时候来看我们规则的第三条 结构体总大小为最大对齐数每个成员变量都有一个对齐数的整数倍。
我们上述结构体的最大对齐数为int型的4但是现在我们只占用了9个字节并不是4的整数倍所以我们还得浪费3个字节达到12个字节才是我们最终的结果。
下面我们来看最后一个例子 struct Str3 { double a; char b; int c; }; struct Str4 { char a; struct Str3 s3; double c; }; 我们来计算Str4这样一个嵌套结构体的大小。
经过我们上边的学习已经能够很容易的算出Str3的大小为16个字节。下边我们来计算Str4。
第一个为char型放在地址为0的位置占用一个字节。
第二个为struct Str3结构体类型大小为16个字节那么根据我们的规则4嵌套的结构体对齐到自己内部的最大对齐数的整数倍处那么Str3内部的最大对齐数为double类型的8所以要是8的倍数很显然1并不是8的倍数所以要浪费7个字节从标号为8的位置开始占用16个字节。
第三个为double类型大小为8个字节对齐数为8前边刚好占用了24个字节是8的整数倍所以我们就从标号为24的位置开始占用8个字节。 这样我们总共就是占用了32个字节。
到这里我们就讲完了通过结构体内存对齐的规则来计算结构体大小的知识。
那么小伙伴们是否有个疑惑我们为什么就非得对齐呢 2.为什么要对齐
我们通过查阅大量的资料最终得出以下两点
1.平台原因移植原因
不是所有的硬件平台都能访问任意地址上的任意数据某些硬件平台只能在某些地址处取某些特定的类型的数据否则就会抛出硬件异常。
数据结构尤其是栈应该尽可能的在自然边界上对齐。
原因在于为了访问未对齐的内存处理器需要做两次内存访问而对齐的内存访问仅需要一次访问。
总体来说
结构体的内存对齐是拿空间来换取时间的做法。牺牲空间来换取效率。
那么有没有什么办法能够帮助我们即能够提升效率又能节省空间呢 3.节省空间和提升效率的方法
1让占用空间小的成员尽量集中在一起 struct Str1 { char a; char b; int c; }; struct Str2 { char a; int b; char c; }; 就比如还是我们这两个结构体成员变量一模一样但是大小却不一样但是Str1的空间是小于Str2的所以第一种方法就是让占用空间小的成员尽量集中在一起。
2修改默认对齐数
我们知道默认对齐数这个规则对我们的空间占用影响很大那我们便可以通过修改默认对齐数的方法来实现节省空间和提升效率。
那么默认对齐数该如何修改呢
通过#pragma这个预处理指令来改变。
#includestdio.h
#pragma pack(1)//将默认对齐数修改为1
struct Str1
{char a;char b;int c;
};
#pragma pack()//恢复默认对齐数的原值
struct Str2
{char a;int b;char c;
};
int main()
{int num1 sizeof(struct Str1);int num2 sizeof(struct Str2);printf(%d\n, num1);printf(%d\n, num2);
}
我们通过#pragma pack()这个指令可以将默认对齐数修改为()内的值比如我们上述代码修改为1 修改之后默认对齐数就固定为1每个数据都对齐到1的整数倍同时也要记得及时恢复默认对齐数的原值确保只有这一块的结构体我们需要修改以免发生错误。
来看结果 除此之外我们还有第三种方法那就是——位段。 三.位段
讲完了结构体的内存分配情况之后我们就得紧接着来谈谈结构体实现位段的能力。 1.什么是位段
位段的出现是为了让结构体更加节省空间。
位段的声明和结构体是类似的有两处不同
位段的成员必须是int、unsigned int 、signed int或char类型位段的成员名后边有一个“冒号”和一个数字
来看例子 struct Str1 { char a : 3; char b : 4; char c : 5; char d : 4; }; 位段的位指的是二进制的位数char a : 3就表示a这个数据占用3个bit位。
如果不用位段我们这个结构体就是4个字节的大小但是使用位段之后来看 只用到了3个字节节省了空间。 这种情况适用于能够知道创建的数据大概会占用多少的空间。
2.位段的的内存分配 那么我们上述结构体通过位段实现的8个字节的空间又是怎么来的呢
位段开辟空间是一步一步来的如果是int型就会先开辟4个字节给你用如果不够那就再开辟一个char同样。
我们很清楚一个字节是8个bit位那么a、b、c、d分别为3、4、5、4个bit位3 4 7 8所以a和b共用一个字节剩下一位不够c用那就丢掉再开辟一个。存入c之后剩余3位不够d用便继续丢掉在开辟最终一共开辟3个字节。
虽然位段能够帮助我们节省一大部分的空间但这并不代表着我们可以随便的使用位段。
因为其涉及着很多的不确定因素不能跨平台所以注重可移植性的程序应避免使用位段。 3.位段的跨平台问题
int位段被当成有符号数还是无符号数是不确定的。位段中最大位的数目不能确定。16位机器最大1632位机器最大32位段中的成员在内存中从左向右分配还是从右往左分配标准尚未定义。当一个结构包含两个位段第二个位段成员比较大无法容纳于第一个位段的剩余位时是舍弃剩余的位还是利用是不确定的。
对于第4条我们上边的代码已经能够验证在当前的VS2019编译器下是直接舍弃。 四.枚举
枚举顾名思义也就是一一的列举。
把我们可能需要用到的数据一一列举出来。 一周的七天 一年的月份 一年的四季 这些都能够写成一个枚举类型来一一列举下面我们就来看看枚举的具体用法。
1.枚举类型的定义
定义枚举常量要用到enum enum Season { SPRING, SUMMER, AUTUMN, WINTER }; 这样我们就定义出来一个简单的季节枚举。
值得注意的是每个枚举常量之间都用逗号隔开最后一个枚举常量后边不用跟任何符号而且枚举常量一般都用其英文的大写字母表示。
在枚举类型中枚举常量都表示一个常数从第一个枚举常量开始代表0此后逐个递增因此枚举常量都是int类型。
#includestdio.h
enum Season
{SPRING,SUMMER,AUTUMN,WINTER
};
int main()
{printf(%d\n, SPRING);printf(%d\n, SUMMER);printf(%d\n, AUTUMN);printf(%d\n, WINTER);return 0;
}
结果如下 枚举常量不能在枚举类型外修改但是可以在其定义时修改并且会影响到后边的值
#includestdio.h
enum Season
{SPRING,SUMMER 100,AUTUMN,WINTER
};
int main()
{printf(%d\n, SPRING);printf(%d\n, SUMMER);printf(%d\n, AUTUMN);printf(%d\n, WINTER);return 0;
}
例如我们将SUMMER改为100那么AUTUMN和WINTER也会在此基础上累加。 我们现在也已经了解到枚举其实也是一种定义常量的方式那我们前边也学过#define同样可以定义常量那么为什么非要用枚举类型呢
2.枚举的优点
增加代码的可读性和可维护性。和#define定义的标识符比较枚举有类型检查更加严谨。便于调试。使用方便一次可以定义多个常量。
五.联合体
1.联合体的定义
联合也是一种特殊的自定义类型。
这种类型定义的变量也包含一系列的成员特征是这些成员共用同一块空间所以也叫共用体
#includestdio.h
union Un
{int a;char b;
};
int main()
{union Un un;printf(%d\n, sizeof(un));printf(%p\n, un);printf(%p\n, (un.a));printf(%p\n, (un.b));return 0;
} 来看我们输出一下这个联合体的大小、地址以及其成员的地址 能够看出联合体的大小确实是int型的4个字节且成员变量的地址都相同这就说明它们共用同一块内存空间。 2.联合体的使用
用来判断编译器的大小端存储
#includestdio.h
int check_sys()
{union Un{int a;char b;}u;u.a 1;return u.b;//返回1表示小端返回0表示大端
}
int main()
{int ret check_sys();if (ret 1)printf(小端\n);elseprintf(大端\n);return 0;
}
既然共用一块空间那么我们就可以通过不同类型的字节数来进行大小端的判断。 得出我们当前编译器为小端存储。
对于联合体的具体使用我们指出一个方向当成员变量不需要同时使用时可以使用联合体。 3.联合体大小的计算
联合体的大小至少是最大成员的大小。当最大成员大小不是最大对齐数的整数倍时候就要对齐到最大对齐数的整数倍。
#includestdio.h
union Un
{int a;char b[5];
};
int main()
{printf(%d\n, sizeof(union Un));return 0;
}
来看这个联合体它的大小是多少5吗 并不是而是8。
因为最大对齐数为4,5不是4的整数倍所以就要浪费3个字节达到8。
六.总结
关于自定义数据类型的讲解到这里就结束啦。
今天的文章也是相当的长啊快累死博主我了呜呜呜~~~ 最后还是希望文章能够帮助到大家不要忘记一键三连哦
我们下期再见 文章转载自: http://www.morning.ppbqz.cn.gov.cn.ppbqz.cn http://www.morning.china-cj.com.gov.cn.china-cj.com http://www.morning.pgcmz.cn.gov.cn.pgcmz.cn http://www.morning.yrhd.cn.gov.cn.yrhd.cn http://www.morning.qyfrd.cn.gov.cn.qyfrd.cn http://www.morning.qhjkz.cn.gov.cn.qhjkz.cn http://www.morning.csgwd.cn.gov.cn.csgwd.cn http://www.morning.xdwcg.cn.gov.cn.xdwcg.cn http://www.morning.krlsz.cn.gov.cn.krlsz.cn http://www.morning.kjcll.cn.gov.cn.kjcll.cn http://www.morning.hqlnp.cn.gov.cn.hqlnp.cn http://www.morning.zlnmm.cn.gov.cn.zlnmm.cn http://www.morning.rfxyk.cn.gov.cn.rfxyk.cn http://www.morning.ylkkh.cn.gov.cn.ylkkh.cn http://www.morning.rfbpq.cn.gov.cn.rfbpq.cn http://www.morning.dtmjn.cn.gov.cn.dtmjn.cn http://www.morning.scjtr.cn.gov.cn.scjtr.cn http://www.morning.krnzm.cn.gov.cn.krnzm.cn http://www.morning.rxfbf.cn.gov.cn.rxfbf.cn http://www.morning.benqc.com.gov.cn.benqc.com http://www.morning.czgtt.cn.gov.cn.czgtt.cn http://www.morning.dbfj.cn.gov.cn.dbfj.cn http://www.morning.lfjmp.cn.gov.cn.lfjmp.cn http://www.morning.dmlgq.cn.gov.cn.dmlgq.cn http://www.morning.hhqjf.cn.gov.cn.hhqjf.cn http://www.morning.lynmt.cn.gov.cn.lynmt.cn http://www.morning.bfrff.cn.gov.cn.bfrff.cn http://www.morning.yhrfg.cn.gov.cn.yhrfg.cn http://www.morning.qkrgk.cn.gov.cn.qkrgk.cn http://www.morning.qkrgk.cn.gov.cn.qkrgk.cn http://www.morning.qwhbk.cn.gov.cn.qwhbk.cn http://www.morning.hkpn.cn.gov.cn.hkpn.cn http://www.morning.ktmbr.cn.gov.cn.ktmbr.cn http://www.morning.zrmxp.cn.gov.cn.zrmxp.cn http://www.morning.ykbgs.cn.gov.cn.ykbgs.cn http://www.morning.nqgff.cn.gov.cn.nqgff.cn http://www.morning.tgtrk.cn.gov.cn.tgtrk.cn http://www.morning.zwzwn.cn.gov.cn.zwzwn.cn http://www.morning.qyxnf.cn.gov.cn.qyxnf.cn http://www.morning.pycpt.cn.gov.cn.pycpt.cn http://www.morning.mgtmm.cn.gov.cn.mgtmm.cn http://www.morning.wrdpj.cn.gov.cn.wrdpj.cn http://www.morning.lwnb.cn.gov.cn.lwnb.cn http://www.morning.rxkl.cn.gov.cn.rxkl.cn http://www.morning.gwwky.cn.gov.cn.gwwky.cn http://www.morning.dyght.cn.gov.cn.dyght.cn http://www.morning.xqcst.cn.gov.cn.xqcst.cn http://www.morning.mkfhx.cn.gov.cn.mkfhx.cn http://www.morning.rkjz.cn.gov.cn.rkjz.cn http://www.morning.ndxrm.cn.gov.cn.ndxrm.cn http://www.morning.thrgp.cn.gov.cn.thrgp.cn http://www.morning.nxdqz.cn.gov.cn.nxdqz.cn http://www.morning.yqyhr.cn.gov.cn.yqyhr.cn http://www.morning.mmtbn.cn.gov.cn.mmtbn.cn http://www.morning.qptbn.cn.gov.cn.qptbn.cn http://www.morning.rqnhf.cn.gov.cn.rqnhf.cn http://www.morning.rycbz.cn.gov.cn.rycbz.cn http://www.morning.weiwt.com.gov.cn.weiwt.com http://www.morning.fyskq.cn.gov.cn.fyskq.cn http://www.morning.hqbk.cn.gov.cn.hqbk.cn http://www.morning.bxbnf.cn.gov.cn.bxbnf.cn http://www.morning.xfxnq.cn.gov.cn.xfxnq.cn http://www.morning.plqkz.cn.gov.cn.plqkz.cn http://www.morning.hkcjx.cn.gov.cn.hkcjx.cn http://www.morning.pzss.cn.gov.cn.pzss.cn http://www.morning.nbgfk.cn.gov.cn.nbgfk.cn http://www.morning.rshkh.cn.gov.cn.rshkh.cn http://www.morning.nwynx.cn.gov.cn.nwynx.cn http://www.morning.kzpy.cn.gov.cn.kzpy.cn http://www.morning.qgfhr.cn.gov.cn.qgfhr.cn http://www.morning.lmdkn.cn.gov.cn.lmdkn.cn http://www.morning.lsqmb.cn.gov.cn.lsqmb.cn http://www.morning.jsrnf.cn.gov.cn.jsrnf.cn http://www.morning.wpydf.cn.gov.cn.wpydf.cn http://www.morning.ngqdp.cn.gov.cn.ngqdp.cn http://www.morning.fqzz3.cn.gov.cn.fqzz3.cn http://www.morning.fylsz.cn.gov.cn.fylsz.cn http://www.morning.rsxw.cn.gov.cn.rsxw.cn http://www.morning.rzbcz.cn.gov.cn.rzbcz.cn http://www.morning.plxhq.cn.gov.cn.plxhq.cn