当前位置: 首页 > news >正文

营销网站的建造步骤深圳电商平台网站建设

营销网站的建造步骤,深圳电商平台网站建设,网站浏览构思,网站建设大概【C语言笔记】自定义类型全解一、结构体1、什么是结构体2、结构体的声明与定义2.1、结构体的声明2.2、对结构体成员的访问2.3、对结构体成员的初始化2.4、结构体的不完整声明2.5、结构体嵌套定义3、结构体的自引用3.1、错误的自引用3.2、正确的自引用4、结构体大小的计算4.1、结… 【C语言笔记】自定义类型全解一、结构体1、什么是结构体2、结构体的声明与定义2.1、结构体的声明2.2、对结构体成员的访问2.3、对结构体成员的初始化2.4、结构体的不完整声明2.5、结构体嵌套定义3、结构体的自引用3.1、错误的自引用3.2、正确的自引用4、结构体大小的计算4.1、结构体的内存对齐4.2、柔型数组5、结构体实现位段5.1、什么是位段5.2、位段的注意事项5.3、位段的内存分配二、枚举1、枚举类型的定义2、枚举的优点三、联合体1、联合体类型的声明与定义2、联合体大小的计算一、结构体 1、什么是结构体 在C语言中有一种数据类型称为“聚合数据类型”它能同时存储一个或一个以上的单独数据C中提供了两种类型的聚合数据类型分别是数组和结构体。 我们知道数组一组相同类型的元素的集合但结构体中的元素类型是可以不相同的。 所以数组可以用下标的方式进行反问(因为它每个元素类型相同)而结构体就不能用下标进行访问。 2、结构体的声明与定义 2.1、结构体的声明 结构体的声明形式如下所示 其中tag表示的是结构体的标签名即这个结构体叫什么名字member-list是结构体成员列表它包含了一个或一个以上的结构体成员而variable-list是结构体变量列表它列出了在创建结构体时同时创建的此类型的变量。比如我们现在可以定义一个学生类型的结构体 这里的student就是tag二大括号内部的id、age、name就是这个结构体的成员变量列表。后面的s1、s2就是结构体变量列表而且像s1和s2这样的在结构体声明的时候就创建的变量都是全局变量。 在声明结构体时必须列出它所包含的所有成员。这个列表包括每个成员的类型和名字。 当然这个variable-list也并不是必须要有的甚至这个tag也是可以没有的。 这些后面都会讲到。 但最后那个结尾的分号是千万不能省略掉的 2.2、对结构体成员的访问 对结构体成员的访问在之前将操作符的时候已经遇到过了但今天既然已经讲到了结构体那我们还是再来复习一下吧。 对结构体成员的访问方试有两种分别是直接访问(.)和间接访问(-)点是对结构体变量使用的所以称为直接访问箭头是对结构体指针使用的所以称为间接访问。 比如我们可以再主函数创建了一个学生类型之后直接用点的方式打印其成员变量 也可以通过一个结构体指针指向s后通过指针来进行打印 总之对结构体成员的访问方试有两种具体使用哪一种还是要看场景。 2.3、对结构体成员的初始化 对结构体成员的初始化其实上面就已经用到了和数组一样也是用一个大括号括起来里面再写成员变量的值当然我们也可以像数组一样对结构体成员进行不完全初始化即大括号里只写一个0 通过调试窗口我们可以看到这里不仅是id被置成了0连后面的age也默认置成了0二名字也被置成了空字符串。 当然了如果我们不想按顺序初始化也可以比如说我就想把名字写在前面 这时候就要在成员变量前面加上一个点。当然这样也是可以不完全初始化的不完全初始化的情况下其他未被赋值的成员默认为0。 2.4、结构体的不完整声明 在声明结构体的时候也可以不完全声明比如我们可以把结构体标签明给省略掉 struct {int id;int age;int name[10];char sex[4]; } s1 ;但这样的声明方式的缺陷是你只能像上面一样在创建的时候就定义好全局变量以后你在想用这个结构体来定义变量是不可能的啦因为它连名字都没有没人认识它也没有人能找到它。 所以匿名声明的结构体的使用都是一次性的。 2.5、结构体嵌套定义 结构体也可以嵌套定义即在一个结构体中定义另一个结构体例如: struct Student {int id;int age;struct Name {char first_name[15];char last_name[15];};struct Name name;char sex[4]; };当一个类型A只会在另一个类型B中被使用的时候就可以吧类型A定义在类型B的定义体内这样可以减少暴露在外面的用户自定义类型的个数。 3、结构体的自引用 其实结构体也可以包含一个结构体本身类型的成员的就比如说各位的身怀绝技的老师一定也是另一个更身怀绝技的老师教出来的所以在一个老师的结构体的成员变量中也可以含有一个老师类型的变量。 那我们应该怎样实现结构体的自引用呢 3.1、错误的自引用 struct Teacher {int id;int age;int name[20];struct Teacher teacher; };上面的这种自引用方式有什么问题吗 好像咋一看确实没有什么问题但若是我问你这结构体的大小是多大呢(我们这里先不管结构体大小的计算方法)那一定要包括所有变量的大小啦但是这个teacher的大小又该怎么算呢难道又是继续向里面算又包括了id、age、name 而且还有一个teacher的大小吗 这样算岂不是永无止尽吗。这难道真像人们所说“学无止境”了吗 很显然这种自引用方式是错误的。 正确的饮用方式应该像下面这样 3.2、正确的自引用 struct Teacher {int id;int age;int name[20];struct Teacher *Te; };我们其实只需要通过老师找到老师的老师即可所以我们只需要存储老师的老师的地址即可这样我们在结构体中存储的就只是个地址就并不会出现向上面一种方式那样的无限循环的情况了。 4、结构体大小的计算 这一块知识算是结构体中比较重要的知识了也是相对来说比较难的知识。 比如我们现在有一个这样的结构体 struct A {char a;int b;double d; };我问你sizeof(struct A)等于多少或者A变量所占的内存空间是多大 你能立刻回答我吗 是不是a的1字节加上b的4字节再加上d的8字节等于13字节呢 但最后如果我们在屏幕上打印出它的大小就会发现并不是13而是16 这到底是怎么一个原理呢 4.1、结构体的内存对齐 想要搞清楚结构体是怎样计算大小的就一定要先搞清楚结构体在内存中是怎样“对齐”的。 其实结构体成员变量在内存空间中的存储并非是像我们想当然那样一个紧挨着一个存放的。结构体成员变量在存储的时候是按照一定的规则存储的这些规则总结起来就以下四条 第一个成员在结构体变量偏移量为0的地址处。其他成员变量要对齐到某个数字对齐数的整数倍的地址处。 对齐数 “编译器默认的一个对齐数 与 该成员大小的较小值”。结构体总大小为最大对齐数每个成员变量都有一个对齐数的整数倍。如果嵌套了结构体的情况嵌套的结构体对齐到自己的最大对齐数的整数倍处结构体的整体大小就是所有最大对齐数含嵌套结构体的对齐数的整数倍。 这咋一看好像信息量有点儿大啊但不没关系我来带着大家一条一条来看一条一条地来解释就拿上面的例子来举例 struct A {char a;int b;double d; };第一条规则的意思是不管你第一个成员变量的类型是什么占用几个字节都是从地址偏移量为0(也就是起始位置)的位置开始存放的。 第二条规则说的是当你从第二个成员变量开始你就要考虑“对齐数”了你的变量要放到“对齐数”的整数倍的地址偏移量处该对齐数为**“编译器默认对齐数和该成员变量大小的较小值”** 。 我这里使用的编译器是vsvs的默认对齐数为8二这里的变量b的类型是int4字节所以对齐数自然就是4。所以我们在偏移量为4的地址开始存放b。 有了以上的规则我们就可以一直存储我们的变量了当我们所有的成员变量都按照以上规则存储完了之后 是不是就完事了呢我们的结构体是不是就是16字节了呢 其实还没有这时候就要用到我们的第3条规则了通过规则2我们可以算出这三个变量a、b、d的对齐数分别是1、4、8所以我们的最大对齐数是8我们看看现在的结构体大小为16字节正好是8的整数倍。所以我们的结构体A的大小就是16字节。 但要是我们活生生的在A中再加入一个成员变量e那结果就大不同了 当我们存完所有的成员变量之后发现结构体的大小为20个字节并不是最大对齐数8的整数倍所以这时要多开辟出4个字节的空间凑成24个字节才够8的整数倍。 但当我们结构体中又包含了其他结构体时呢?其大小又该怎么计算呢 这时候就要用到第4条规则了 例如我们现在有这两个结构体 struct C {char a;int b;char c; };struct D {int e;short s;struct C c1;int f; };通过上面的方法我们可以很容易的算出C的大小为12字节 但这个C放到D里面又是怎么放的呢其实这里我们可以把C看成是一个整体(例如一个很大的变量)而它的对齐数就是其自身的成员变量中最大对齐数中的最大值。我们这里很容易得知C的对齐数就是4所以我们就可以把C放到D中了 我们可以计算得知此时D所占的空间大小为24字节而我们结构体D整体的大小是所有对对齐数(含嵌套结构体)的整数倍是否满足呢 我们可以很容易得知此时的整体最大对齐数其实就是4所以是满足的。所以结构体D的大小就是24字节。 4.2、柔型数组 柔型数组这个概念可能你连听都没有听说过但它确确实实是存在的柔型数组指的是结构体中元素允许是未知大小的数组它必须是结构体中的最后一个成员且结构体中的柔性数组前面至少要有一个成员。 例如我们在之前的结构体C中再次增加一个数组成员 struct C {char a;int b;char c;int arr[]; };这里增加的arr就是一个柔性数组。 我们知道C的大小为12个字节那增加了这么一个数组对它的大小有什么影响吗 我们可以来看看 我们可以看到好像确实没有什么影响。 确实sizeof返回的这种结构大小是不包括柔性数组的内存的。 还有一点就是包括柔性数组成员的结构体需要用malloc函数对其进行内存的动态分配并且所分配的内存应该大于结构体的大小以适应柔性数组的预期大小例如我们可以为上面的结构体C开辟一块20字节的内存空间 struct C* s1 (struct C*)malloc(20 * sizeof(char));有人可能会好奇了这里给它开辟了20个字节的空间那它的大小是不是就是20字节了呢 我们可以验证一下 我们会惊奇的发现这里*s1的大小还是12字节连一个字节都没有增加这也恰好说明了结构体的大小其实不包括柔性数组在内。 5、结构体实现位段 5.1、什么是位段 位段的声明与结构体类似但它的成员是一个或多个位的字段。这些不同长度的字段实际存储于一个或多个整型变量中。 一个位段的声明形式如下 struct A {int _a : 2;int _b : 5;int _c : 10;int _d : 30; };位段的声明和任何普通的结构体成员声明相同出了两点以外 1.位段的成员必须是 int unsigned int signed int 或者是 char 属于整形家族类型。 2.在成员后面是一个冒号和一个整数。 位段成员冒号后面的整数表示的是该成员一共占用的字节数也就是该成员最大可以占用的字节数这就起到了一个限制成员大小和节省空间的作用。 5.2、位段的注意事项 位段的使用其实就是为了节省空间限制数据的大小但是位段的不确定性因素太多。所以注重可移植性的程序应该避免使用位段。 位段的不确定性因素大概有以下几点 1.int位段应该被当做有符号数还是无符号数不确定。 2.位段中的成员在内存中是从左向右分配还是从右向左分配不确定。 3.当一个声明制定了两个或两个以上的位段且存在后一个位段比较大无法容纳于前一个位段的剩余位时编译器到底是把后一个位段存放到下一个字节还是直接从前一个位段的剩余部分开始放从而在两个内存位置边界上形成重叠这也是不确定的。 5.3、位段的内存分配 由于位段的不确定性因素太多这里首先进行说明这里演示的环境是 小端机器、int是有符号int、位段成员在内存中是从右向左分配的、这里编译器是把较大的位段放到后一个字节的。 比如说我们现在有这样一个位段 struct A {char _a : 2;char _b : 5;char _c : 7;char _d : 6; };int main() {struct A a { 0 };// 我们给a中的成员赋一些值a._a 5;a._b 10;a._c 7;a._d 20;return 0; }这里遇到了第一个成员_a_a的类型是char所以就会首先开辟一个字节的空间但_a只占两个比特的位置所以在赋值5给它的时候就会发生截断实际放的是01。 这里遇到的第二个成员_b只占5个比特之前开辟出的1个字节的空间是足以存放它的所以就不用开辟新的空间因为10的二进制序列才4比特位所以_b是完全容得下的所以实际存储的就是10本身。 当遇到第3个成员_c时剩余的一个比特位已不足以容纳_c了所以要新开辟一个字节的空间而_c的7个字节是足以存放下7这个整型的所以_c里存放的就是7。 后面的操作也是和前面的一样了当我们放完所有的成员之后我们可以看到A的大小应该是3字节而A中的序列应该是像下图这样 我们可以到内存中去检验一下 我们发现sizeof(struct A)确实是3而且内存中的前三个字节也确实是29 07 14。 所以对于位段的内存分配方式我们也清楚了。 二、枚举 在现实生活中总有一些东西是能够一一列举出来的比如人的性别就男女两种一周就只有7天星期一到星期天。 这对应到C语言中就是枚举类型了。 1、枚举类型的定义 枚举类型的定义形式就像下面这样 enum Day {Mon,Tues,Wed,Thur,Fri,Sat,Sun };上面的enum Day就是一个枚举类型大括号{}中的内容就是枚举类型可能的取值也成为了枚举常量。 而这些枚举常量也都是有值的在未进行初始化的情况下它们的值从第一个常量开始默认为0往下以1递增。 如果我们现在打印这些常量的值就可以看到 它们默认是0到6。 如果我们对中间一个赋初始值的话就会看到 也就是说枚举中的常量如果不初始化的话都是向下递增的只是初始化后就会按照初始化的值为基准向下递增。 2、枚举的优点 枚举的优点可以总结为以下5点 增加代码的可读性和可维护性和#define定义的标识符比较枚举有类型检查更加严谨。防止了命名污染封装便于调试使用方便一次可以定义多个常量 第一点增加代码的可读性和可维护性其实就是使代码读起来更直观不用老是前后对照比如我们想实现一个多功能的计算器可以执行整数的加减乘除运算那我们必定就要设计一个方案来根据输入判断你要执行的操作我们可能会这样设计 void menu() {printf(***************0、exit***************\n);printf(*******1、Add 2、Sub********\n);printf(*******3、Mult 4、Div********\n);printf(*************************************\n); }int main() {int input 0;do {menu();printf(请选择);scanf(%d, input);switch (input) {case 1:// 执行加法运算break;case 2:// 执行减法运算break;case 3:// 执行乘法运算break;case 4:// 执行除法运算break;case 0://退出程序break;default:printf(输入有误请重新输入\n);break;}} while (input);return 0; }这样确实没问题但如果我们有时候忘记了那个数字对应的是哪一种运算好像又要去查一查菜单这样好像有点儿麻烦。 这时候我们就可以用枚举来帮我们来解决这个麻烦了 enum Option {Exit,Add,Sub,Mult,Div };这样我们就可以将我们的选项全都换成枚举了 int main() {int input 0;do {menu();printf(请选择);scanf(%d, input);switch (input) {case Add:// 执行加法运算break;case Sub:// 执行减法运算break;case Mult:// 执行乘法运算break;case Div:// 执行除法运算break;case Exit://退出程序break;default:printf(输入有误请重新输入\n);break;}} while (input);return 0; }这样不就直观多了吗 我们知道 #define定义的标识符做的工作只是“替换”而非定义一个类型所以 #define定义的标识符是没有类型可言的。但枚举是有类型的这就意味着我们要想把非枚举类型的数据赋值给枚举类型是非法的。所以枚举更严格。 枚举定义的常量只能在枚举类型里使用而 #define定义的符号是全局的任何地方都可以使用也就是说define定义了一个符号后其他地方就不能出现与它同名的符号了这就叫做命名污染。而枚举定义的常量就不存在这种问题其他地方也可以有与枚举常量同名的符号。 而易于调试是相对于define定义的符号来说的define定义的符号所做的工作是“替换”而“替换”后我们是看不见define定义的那个符号的比如 所以在调试的时候我们并不知道那个变量可能会是用X这个标识符算出来的也就不便于我们调试。枚举是有类型的它在调试中是可以清楚地看到其类型的 三、联合体 联合体也是一种特殊自定义类型它与结构体非常类似。但和结构体不同的是联合体的所有成员引用的都是内存中的相同位置。 1、联合体类型的声明与定义 联合体的声明形式如下 union Un {char c;int i; };定义联合体的形式如下 union Un un;2、联合体大小的计算 联合体的特点就是所有成员共用一块空间这就是的联合体的大小至少是联合体中最大的成员的大小例如我们现在有下面这样的一个联合体 union Un {char c;int i; };我们可以打印出它的大小来看看 就会发现果然是4。 而且联合体内的成员在同一时间里只能有一个相同的值。例如我们创建一个联合体a将a.i赋值成1然后打印a.c就会发现a.c也是1 当你有两个变量而且每次时使用都只可能用到其中的某一个时就可以考虑将这两个变量放到联合体中所以联合体的存在事实上也是为了节省空间的。
http://www.w-s-a.com/news/247677/

相关文章:

  • 网站模板搭建已经建网站做外贸
  • 网站建设选哪个wordpress实现微信登录界面
  • 网页设计网站哪个公司好学网站开发要多少钱
  • 商务网站建设ppt做视频分享网站
  • WordPress网站根目录有哪些wordpress用户等级
  • 私人装修接单网站重庆制作企业网站
  • 易企秀网站怎么做轮播图什么是网站版面布局
  • 网站开发先写什么后写什么做网站公司专业
  • 中山网站建设文化外贸公司的网站建设模板
  • 美食网站开发开题报告wordpress第三方支付接口
  • 有哪些网站可以卖自己做的图片简洁大方的网站首页
  • 四川建设网电子招投标网站网站酷站
  • 凯里网站建设如何收费网站建设php怎么安装
  • 网站建设专业网站设计公司物格网一站式建站价格
  • seo网站培训优化怎么做如何给网站做下载附件
  • php网站建设文献综述怎么样提高网站排名
  • 专用车网站建设wordpress半透明
  • 石狮网站建设哪家好wordpress 3.9 漏洞
  • 为何建设单位网站找网络推广策畿
  • 用网站模板做网站动漫制作专业学校前十名
  • 网页 代码怎么做网站网站建设与维护课程设计
  • 网站制作哪家公司好企业名录联系电话
  • 做的网站怎么上传到网上wordpress图片之间空一行
  • 腾讯云建设网站视频vi报价单
  • 个人网站发布怎么做建设银行网站收款怎么打明细
  • 网站整体色调网站建设都有什么类型
  • 比较简洁大方的网站软件工程四大方向
  • 大家称赞的网站建设常德小学报名网站
  • 做网站怎么建文件夹百度网盘搜索神器
  • 企业有域名怎么做网站淘宝推广平台