当前位置:首页 » 《随便一记》 » 正文

【c语言】——结构体千字解读,看完你肯定不会有任何结构体的疑惑

23 人参与  2024年03月05日 08:26  分类 : 《随便一记》  评论

点击全文阅读


一.前言

在学习初期,我们接触了很多整型,浮点型,字符型等变量,其实结构体从整体上看和他们都差不多

其实现阶段对结构体有疑惑的无疑是

1.用的少,老是忘记怎么用 

2.对结构体的知识点不是很牢,经常弄混

第一点只能自己找题目练习,第二点不用担心,看完就可以豁然开朗了

 二.结构体的声明

首先先看结构体的模板:
struct stu{member - list//成员列表}variable - list;//变量列表,最后有一个分号不要忘记
例如表述一个学生
struct stu{char name[20];//名字int age;//年龄char sex[5];//性别};//分号不能丢

这里的变量其实有两种表示方法,比如可以想模板一样在后面加上变量名就可以

struct stu{char name[20];int age;char sex[5];}s,a,b;

因为之前说过他整体上和其他类型差不多,所以,也可以像其他类型一样在main函数里面创建

(细细品味这句话)

struct stu{char name[20];int age;char sex[5];}int main(){struct stu s;//创建结构体变量时,要把结构体的名字写全,不能只写一个structreturn 0;}
下面就到了容易弄混的地方了,也就是这里导致很多人忘记在结构体后面创建变量一会是变量,一会又是结构体的名字
typedef struct stu{char name[20];int age;char sex[5];}stu;//这里因为前面的typedef所以这个结构体的名字就变成了stu;//后面在创建变量的时候就可以直接使用stu了;

以上就是结构体的基本声明和创建还有一些容易弄混的地方,其实结构体还有一些特殊的声明

结构体声明的时候可以 不完全声明,这种叫做匿名结构体类型
struct {//没有名字char name[20];int age;char sex[5];}stu;

从这里你可以很清楚的看到这种声明方式和上面的不一样,既然不一样,那肯定是有区别的,

区别就在于这种匿名结构体只能使用一次,也就是说它只能在结构体后面创建变量,不能在main函数中重复创建,也就是说匿名结构体创建的变量,都在main函数之外,都是全局变量

还有就是如果你创建两个匿名结构体,编译器会认为他们是不同类型的,因为他们没有确定的类型名。但是这种匿名结构体也有好处,就是嵌套在结构体的结构体为匿名的时候,可以直接访问,这样比较方便,反之还需要特殊引用去处理,这里不展示了,知道就好

三.结构体的自引用

 顾名思义,就是自己引用自己

但也没有我们想的那么简单,下面看一段代码思考一下就知道了

struct stu {int age;struct stu s;};//思考这个结构体有多大?

 这个结构体会大到无穷,就感觉像一个无限的递归一样,所以是不合理的

正确的应该是把第二个元素换成指针形式,这样通过指针我们就知道这个结构体是多大了,

struct stu {int age;struct stu* next;};

 这里用到了数据结构的知识,知道有这么回事就行了

上面说了结构体的大小问题,那么我们是怎么去计算结构体大小的呢?

四.结构体内存对齐

首先先看下面一段代码

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;struct stu {char b;int age;char a;};struct node {char a;char b;int age;};int main(){cout << sizeof(struct stu) << endl;cout << sizeof(struct node);}

计算的是他们的大小,可以先思考一下,他们的大小是否相同

这么可以看到是不一样的,这是因为结构体有自己的内存对齐规则

  1.结构体的第一个成员对齐到和结构体变量的起始位置偏移量为0的地址处

  2.其他成员对齐到某个数字(对齐数)的整数倍处

对齐数=编译器默认的一个对齐数和变量本身大小的较小值

  3.结构体的总大小为最大对齐数的整数倍

  4.如果嵌套了结构体的时候,结构体的整体大小就是所以最大对齐数的整数倍

很多人应该看完,还是一头雾水,就用上面的例子来解释

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;struct stu {char b;//大小为1,默认对齐数是8(编译器不一样,默认对齐数就不一样),1<8那么1是他的对齐数int age;//同理,他的对齐数是4;char a;//对齐数是1;};//那么从第一个规则我们可以知道,第一个变量是在偏移量为0处也就是第一个位置,占一个字节//因为第二个变量对齐数是4,(2,3不是4的整数倍,但4是)所以第二个变量从第四给字节开始往后占4个字节//第三个变量对齐数是1,第二个变量以后来到了第8个字节位置,所以又8是1的整数倍,所以把它放进去//最后他们三个变量的最大对齐数是4,所以看9是否是4的整数倍(因为从0开始到8一共9个字节),是,那么它的大小就是9,不是,则往后找,直到找到4的倍数位置,所以这里找到12;struct node {char a;char b;int age;};//这里的计算可以照猫画虎,很容易就得出它的大小为8;int main(){cout << sizeof(struct stu) << endl;cout << sizeof(struct node);}

对齐规则你可以用不到,但是你不能不知道,这里只是用文字进行描述,没有画图,如果有什么疑问可以在评论区发言

五. 结构体传参

结构体传参可以分为两种,结构体传参和结构体地址传参

 虽然分为两种方式,但是大多都是用的结构体地址传参,因为用结构体传参参数压栈的系统开销比较大,所以一般不用第一种

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;struct stu {int age;char name[20];};void print(struct stu* p) {cout << p->age;//指针用->,变量用.}//void print(struct stu p){cout<<p.age;}int main(){struct stu s = { 20,"sdadasd" };print(&s);//print(s);return 0;}

六.结构体实现位段

1.位段的成员必须是unsigned int ,int ,signed int或者是char类型

2.位段的成员名后面一个冒号和一个数字

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;struct stu {//开始的时候会创建一个字节的空间,然后放进去,如果不够再创建一个字节int a : 2;//这里的数字代表2位二进制位,下面同理int b : 5;int c : 10;int d : 30;};int main(){struct stu s = { 0 };s.a = 10;//转化位二进制,然后放进开辟的空间里面去,可能空间不够会有一部分截断s.b = 12;s.c = 3;s.d = 4;return 0;}

为什么要有位端呢,其实它的作用就是节省空间,但是它也有弊端,就是不能跨平台而且涉及了很多不确定的因素。

这里还有一个点就是位段的几个成员是共用一个字节的,所以我们在输入的时候,直接用scanf取地址输入是不行的,因为内存中分配一个地址,一个字节内部的bit位是没有地址的。

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;struct stu {int a : 2;int b : 5;int c : 10;int d : 30;};int main(){struct stu s = { 0 };scanf("%d". & s.a);//错误//正确int x;scanf("%d", &x);s.a = x;return 0;}

如果你看到这里,那么相信你一定对结构体有一定的了解和理解了,下面就是多去练习,发现问题

希望这篇文章对大家有帮助,如果有任何疑问可以发在评论区

后面会更新动态内存和文件的相关知识,请持续关注我


点击全文阅读


本文链接:http://zhangshiyu.com/post/73880.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

最新文章

  • 京圈佛子破戒后,我改嫁京圈纨绔(沈墨渊,白晶晶)
  • 前世被闺蜜害死,重生后我让她从太子妃变疯女苏婉儿,清歌完本_前世被闺蜜害死,重生后我让她从太子妃变疯女(苏婉儿,清歌)
  • 全书浏览七零军嫂太彪悍,带三宝上军区离婚(沈清落,陈桂花,陆有为)_七零军嫂太彪悍,带三宝上军区离婚(沈清落,陈桂花,陆有为)全书结局
  • 今天也没变成昨天(周扬陈默)全书免费_(周扬陈默)今天也没变成昨天后续(周扬陈默)
  • 重生后,秦总非要父以子贵(许沐晴,秦越泽)全书浏览_重生后,秦总非要父以子贵全书浏览
  • 他嫌弃我喝两块钱豆浆上不了台面,我结婚后他又哭又闹全书万照,白青青在线
  • 昭然若梦前尘烬列表_昭然若梦前尘烬(温昭然方池雲)
  • 导师借我股票账号,我倒欠五十万(孟潇潇,宁薇)_导师借我股票账号,我倒欠五十万孟潇潇,宁薇
  • 拒绝把外卖券给舍友,竹马送我到迪拜捡垃圾(周钰泽,蒋清清,思源)全书浏览_拒绝把外卖券给舍友,竹马送我到迪拜捡垃圾全书浏览
  • 我的人生,你已出局(程森凌古楚文)_我的人生,你已出局程森凌古楚文
  • 穿书成病娇女配,睁眼就签下离婚协议书(朱楼)_穿书成病娇女配,睁眼就签下离婚协议书
  • 老婆逼我给白月光捐肾,我死后她悔疯了(宋逸晨沈墨白)全书浏览_老婆逼我给白月光捐肾,我死后她悔疯了全书浏览

    关于我们 | 我要投稿 | 免责申明

    Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1