尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

深度剖析 —— 结构体

深度剖析 —— 结构体 系列文章目录深度剖析数据深度剖析递归深度剖析结构体深度剖析动态内存管理深度剖析文件操作深度剖析预处理文章目录系列文章目录前言一、示例问题创建通讯录1.通讯录的需求二、结构体1.建立结构声明2.创建结构变量3.初始化结构体4.访问结构成员三、结构体数组1.创建结构数组2.数组的初始化3.数组访问成员四、嵌套结构1.结构体的嵌套2.嵌套的初始化3.嵌套访问成员五、结构体指针1.创建结构指针2.指针的初始化3.指针访问成员六、结构体的计算1.空间换取时间2.结构体的存储总结前言在设计程序时最重要的步骤之一是选择表示数据的方法。许多情况下数组已经部能很好的满足我们的需求而结构变量通过创造新的形式提高了我们表示数据的能力。一、示例问题创建通讯录1.通讯录的需求通讯录就需要一种能包含数字的数据形式而切要保持各信息的独立信息名字年龄性别电话地址功能增加删除查找修改排序二、结构体1.建立结构声明结构声明(structure declaration)描述了一个结构组织布局structPeoInfo{charName[8];charSex[4];intAge;charTelephone[12];charAddress[12];};该声明描述了一个由四个字符数组和一个整型变量组成的结构。该声明并未创建实际的数据只是描述了该对象由什么组成。从本质上看结构声明创建了一个名为struct PeoInfo的新类型(int double等类型等价) 。struct它表明其后的是一个结构struct PeoInfo则是这个结构的名称2.创建结构变量结构变量定义了一个struct PeoInfo类型的变量structPeoInfoMail;此时此刻才向堆栈申请了一块sizeof(struct PeoInfo)大小的空间(这里是为了便于理解所以恰好设置了40个字节的大小布局后面会有结构体大小的计算详解)。3.初始化结构体struct PeoInfo类型也可以直接进行初始化structPeoInfoMail{小明,男,18,11111111111,某小区};struct PeoInfo和int等其他类型一样可以直接进行赋值它的内容需要由花括号括起来各初始化项由逗号进行分隔。4.访问结构成员结构体成员的基本访问(对象.访问成员或指针-访问成员)printf(%s,Mail.Name);printf(%s,Mail.Sex);printf(%d,Mail.Age);printf(%s,Mail.Telephone);printf(%s,Mail.Address);本质上Name、Sex、Age、Telephone、Address都是struct PeoInfo的下标就像数组的下标0、1、2、3一样数组是用[ ]来访问所在下标位置的元素 而结构体则是用.和-来访问成员。三、结构体数组1.创建结构数组创建结构数组创建明其他类型的数组类似structPeoInfoMail[100];与其他类型一样数组的每一个元素又是struct PeoInfo类型的元素。2.数组的初始化与其他数组一样只能在创建的时被直接初始化structPeoInfoMail[20]{{小明,男,18,11111111111,某小区},{小红,女,18,11111111111,某小区}};下面的这种写法是错误的Mail[0]{小明,男,18,11111111111,某小区};//错误示例3.数组访问成员找到结构数组的某一个元素的下标进行访问printf(%s,Mail[0].Name);printf(%s,Mail[0].Sex);printf(%d,Mail[0].Age);printf(%s,Mail[0].Telephone);printf(%s,Mail[0].Address);四、嵌套结构1.结构体的嵌套当我们需求更丰富时就需要在结构体中嵌套一层结构体//成员信息structPeoInfo{charName[8];charSex[4];intAge;charTelephone[11];charAddress[13];};//通讯录structContact{structPeoInfoData[MAX];//存放增加进来的人的信息(此处为结构体的嵌套)intcount;//记录当前通讯录中有效信息的个数}Contact;2.嵌套的初始化嵌套式结构体建议一个一个进行赋值而非直接初始化//方法一strcpy(Mail.Data[0].Name,小明);strcpy(Mail.Data[0].Sex,男);Mail.Data[0].Age18;strcpy(Mail.Data[0].Telephone,11111111111);strcpy(Mail.Data[0].Address,某小区);//方法二scanf(%s,Mail.Data[0].Name);scanf(%s,Mail.Data[0].Sex);scanf(%d,Mail.Data[0].Age);scanf(%s,Mail.Data[0].Telephone);scanf(%s,Mail.Data[0].Address);当结构体过于复杂时不建议像下面代码这样直接初始化当嵌套更加复杂时直接初始化会非常困难。structContactMail{{{小明,男,18,11111111111,某小区},{小红,女,18,11111111111,某小区}},20};3.嵌套访问成员嵌套成员依然是一层一层的去访问(与前面一模一样)printf(%s,Mail.Data[0].Name);printf(%s,Mail.Data[0].Sex);printf(%d,Mail.Data[0].Age);printf(%s,Mail.Data[0].Telephone);printf(%s,Mail.Data[0].Address);五、结构体指针1.创建结构指针指向结构体的指针structContact*PMail;2.指针的初始化当结构体过于复杂时建议一个一个进行赋值//方法一 (结构体过于复杂时不推荐该方法)structContactMail{{{小明,男,18,11111111111,某某小区},{小红,女,18,11111111111,某某小区}},20};structContact*PMailMail;//方法二strcpy(PMail-Data[0].Name,小明);strcpy(PMail-Data[0].Sex,男);PMail-Data[0].Age18;strcpy(PMail-Data[0].Telephone,11111111111);strcpy(PMail-Data[0].Address,某小区);//方法三scanf(%s,PMail-Data[0].Name);scanf(%s,PMail-Data[0].Sex);scanf(%d,PMail-Data[0].Age);scanf(%s,PMail-Data[0].Telephone);scanf(%s,PMail-Data[0].Address);3.指针访问成员访问时可以*指针.或-直接访问printf(%s,PMail-Data[0].Name);printf(%s,PMail-Data[0].Sex);printf(%d,PMail-Data[0].Age);printf(%s,PMail-Data[0].Telephone);printf(%s,PMail-Data[0].Address);六、结构体的计算1.空间换取时间效率至上在尽可能不浪费空间的情况下尽可能的提高运行的效率来达到我们想要的结果。所以在结构体的存储方面我们选择牺牲较少的空间来降低计算机计算的时间复杂度便于更快的运行程序。2.结构体的存储存储法则第一个成员在与结构体变量偏移量为0的地址处。其他成员变量要对齐到某个数字对齐数的整数倍的地址处。(对齐数 编译器默认的一个对齐数 与 该成员大小的较小值)。结构体总大小为最大对齐数每个成员变量都有一个对齐数的整数倍。如果嵌套了结构体的情况嵌套的结构体对齐到自己的最大对齐数的整数倍处。结构体的整体大小就是所有最大对齐数含嵌套结构体的对齐数的整数倍。计算结构体的偏移量offsetof (type, 成员)修改默认最大对齐数8#pragma pack(最大对齐数)一般设置为2的n次方//计算下面代码的大小structBook{chartitle[3];intcount;shortvalue;};题解int的对齐数是4而char占了3个字节显然不是4的整数倍于是浪费1个空白字节从而凑出4个字节恰好为int对齐数4的整数倍此时此刻占了8个字节。short的对齐数是2个字节8恰好是2的整数倍所以short紧跟在int后面占2个字节此时占用10个字节但10并不是最大对齐数4(默认对齐数和int的对齐数取较小值)的整数倍所以还要再浪费2个空白字节最终结构体占用12个字节的大小。总结结构体提供了再相同的数据对象中存储多个不同类型数据项的方法。可以创建一个具体的结构模板并声明相应的变量。通过.运算符和-运算符可以访问结构中的各个成员。它使得我们在处理问题时有更佳灵活的方式去解决。
返回列表