结构体(c语言)

一.结构体

1.结构的基础知识

        结构是一些值得集合,这些值称为成员变量,结构得每个成员可以是不同类型的变量

2.结构体的声明

struct tag//结构体名称{member-list;//成员变量}variable-list;//全局变量

例:描述一个学生

struct Stu
{int age; //年龄char name[10];//名字
}//s1,s2,s3为全局变量;int main()
{
//s4,s5为局部变量struct Stu s4;struct Stu s5;return 0;
}

3.结构体的初始化

struct Stu
{int age;char name[10];
};int main()
{//pa为结构体的变量struct Stu pa = { 10,"lisi" };//对结构体进行初始化//pa.age,pa.name 为访问结构体的成员printf("%d %s", pa.age, pa.name);return 0;
}

结构体中含有指针怎么初始化

struct S
{char name[100];int* ptr;};int main()
{int a = 100;//用空指针变量来对结构体进行初始化struct S s = { "abcdef",NULL };return 0;
}

4.结构体的重命名

typedef 把struct Stu 直接变成student,以后要写结构体时,直接写student即可,不用再写struct Stu

typedef struct Stu
{int age;char name[10];
}student;//这里的student是结构体类型int main()
{//pa为结构体的变量student pa  = { 10,"lisi" };//pa.age,pa.name 为访问结构体的成员printf("%d %s", pa.age, pa.name);return 0;
}

5.结构体的自引用

结构体内部包含一个指向自身类型的指针,这叫做结构体的自引用

struct Node
{int data;//这是一个指向Node结构体的指针,用与指向下一节点struct Node* next;
};int main()
{struct Node n1;struct Node n2;//这行代码将n1的next指针指向n2的地址//从而n1与n2产生了联系n1.next = &n2;return 0;
}

6.结构体的嵌套

就是一个结构体中套了一个结构体

struct S
{int a;char c;
};
struct B
{float f;struct S s;
};int main()
{//结构体变量的初始化struct S s2 = { 100,'q' };//按照自己的顺序来初始化struct S s3 = { .c = 'r',.a = 2000 };//嵌套结构体的初始化struct B sb = { 3.14f,{10,'a'} };//打印嵌套结构体printf("%f %d %c", sb.f, sb.s.a, sb.s.c);//sb.s.a的意思是用结构体B的变量sb进入到B的结构体中来访问结构体的成员//.s就是进入到结构体S中,最后.c就是访问S中的结构体成员return 0;
}

7.结构体的内存对齐(计算结构体的大小)

 知识引入:

                     1.结构体的第一个成员永远放在偏移量为0的地址处

                     2.从第二个成员开始,以后的每个成员都要对齐到(某个对齐数)的最大整数倍

                       对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。

                         VS中默认的值为8

                     3.当成员全部存放进去时,结构体的总大小必须是所有成员对齐数

                      的最大对齐数的整数倍。

                     4.如果嵌套结构体,嵌套的结构体要对齐到自己成员最大对齐数的整数倍数,

                       整个结构体的大小必须是最大对齐数整数倍(包含嵌套的结构体成员对齐数)


例:求下面代码结构体所占空间大小

看图理解👇

          答案是12个字节

使用offsetof计算偏移量

代码如下👇

//offsetof的头文件
#include<stddef.h>
struct S
{char c;int a;
};int main()
{//offsetof 可以用来算偏移量printf("%d\n", offsetof(struct S, c));//a是写在偏移量为4的地址处,因为是从0开始的,到4结束printf("%d\n", offsetof(struct S, a));return 0;
}

使用#pragma可以修改默认对齐数

include <stdio.h>#pragma pack(4)//设置默认对齐数为4struct S1{char c1;int i;char c2;};#pragma pack()//取消设置的默认对齐数,还原为默认

为什么存在内存对折

1.平台原因

不是所有硬件平台上都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则会抛出数据异常。

2.性能原因

数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。


8.结构体的函数传参

1.当结构体是普通变量(非指针类型)时,使用.操作符来访问结构体中的成员

2.当结构体是通过指针来引用时,使用->操作符来访问结构体中的成员。

struct S
{
int data[1000];
int num;
};
//s为结构体变量
struct S s = { {1,2,3,4}, 1000 };
//结构体传参
void print1(struct S s)
{
// . 应用于结构体传参printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps)
{//->应用于指针传参printf("%d\n", ps->num);
}
int main()
{print1(s);  //传结构体print2(&s); //传地址return 0;
}
我们如何从结构体传参和指针传参中选择

 函数传参的时候,参数需要压栈,会有时间和空间上的系统开销。

1.如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大

,所以会导致性能下降。

2.如果使用指针的时候,参数压栈的系统开销比较小,性能会提升很多

总结:

结构体传参的时候,要传结构体的地址

9.位段

1.位段的成员必须是unsigned intsigned int

2.位段的成员后边必须有一个 数字

//结构体内部是位段
struct A
{int _a : 2;//:后边的数字是bit(比特)int _b : 5;int _c : 10;int _d : 30;
};

位段的内存分配

1. 位段的成员可以是 int unsigned int signed int 或者是 char 类型

2. 位段的空间上是按照需要以4个字节( char (属于整形家族)类型 int )或者1个字节( char )的方式来开辟的

3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段

注意:这是在vs编译器下的位段分配方式!!👇

在VS编译器中,先开辟一个字节空间,如果不够用,则会继续开辟

分配到内存的比特位是从右向左进行使用的。位段中的成员在内存中从左向右分配

分配的比特位不够用,直接浪费掉,直接开辟下一个字节空间

位段的跨平台问题

1.int位被当成有符号位,还是无符号位不确定

2.位段的最大数目不确定,在16位机器上是16,在32位机器上是32,在64位机器上是64,(如果位段是27,在16位机器上就不适用了)

3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。

4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是 舍弃剩余的位还是利用,这是不确定的。

总结:

位段相对于结构体,可以节省很多空间,但是有跨平台问题出现


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/470770.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GIS空间分析案例---城市公共设施配置与服务评价

今天给大家带来新的GIS案例分析——“城市公共设施配置与服务评价” 数据准备 本案例提供的数据资料如下&#xff1a; 武汉城区.shp&#xff1a;武汉市三环城区范围面要素&#xff1b; 武汉城区&#xff08;去除水系&#xff09;.shp&#xff1a;去除水系后的研究区范围面要…

如何在算家云搭建Peach-9B-8k-Roleplay(文本生成)

一、Peach-9B-8k-Roleplay简介 Peach-9B-8k-Roleplay 是一种聊天大型语言模型&#xff0c;它是通过我们的数据合成方法创建的超过 100K 的对话中微调 01-ai/Yi-1.5-9B 模型而获得的。 也许是 34B 以下参数最好的 LLM。 二、模型搭建流程 1. 创建容器镜像 进入算家云平台的“…

软件工程概论项目(二),node.js的配置,npm的使用与vue的安装

上一章我们配置了git仓库&#xff0c;这一章我们来配置项目需要用的一些其他的环境。 放一个思维导图在这里&#xff0c;可以参考一下&#xff0c;很不全面&#xff0c;没有参考价值,反正我先这样写吧。 参考了这个nodejs的配置&#xff0c;写的很好&#xff1a;https://blog.c…

Android中桌面小部件的开发流程及常见问题和解决方案

在Android中&#xff0c;桌面小部件&#xff08;App Widget&#xff09;是应用程序可以在主屏幕或其他地方显示的一个可视化组件&#xff0c;提供简化信息和交互功能。Android桌面小部件的framework为开发者提供了接口&#xff0c;使得可以创建和更新小部件的内容。以下是Andro…

JAVA题目笔记(十五)经典算法题

一、按要求排序 要求&#xff1a;定义数组并存储一些女朋友对象&#xff0c;利用Arrays中的sort方法进行排序 属性包括&#xff1a;姓名&#xff0c;年龄&#xff0c;身高 按照年龄大小进行排序&#xff0c;年龄一样按照身高排序&#xff0c;身高一样按照姓名字母进行排序。…

【JVM】关于JVM的内部原理你到底了解多少(八股文面经知识点)

前言 &#x1f31f;&#x1f31f;本期讲解关于HTTPS的重要的加密原理~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话不…

【Pikachu】目录遍历实战

既然已经决定做一件事&#xff0c;那么除了当初决定做这件事的我之外&#xff0c;没人可以叫我傻瓜。 1.目录遍历漏洞概述 目录遍历漏洞概述 在Web功能的设计过程中&#xff0c;开发者经常会将需要访问的文件作为变量进行定义&#xff0c;以实现前端功能的灵活性。当用户发起…

如何用C#和Aspose.PDF实现PDF转Word工具

在本篇博文中&#xff0c;我将详细讲解如何用C#实现一个PDF转Word工具。这款工具基于Aspose.PDF库&#xff0c;实现PDF文件转为Word&#xff08;DOC/DOCX&#xff09;格式的功能&#xff0c;并通过用户友好的界面和状态提示提升用户体验。希望通过这篇文章帮助大家理解软件的实…

【图像压缩感知】论文阅读:Self-supervised Scalable Deep Compressed Sensing

tips&#xff1a;本文为个人阅读论文的笔记&#xff0c;仅作为学习记录所用。 Title&#xff1a;Self-supervised Scalable Deep Compressed Sensing Journal&#xff1a;IJCV 2024 代码链接&#xff1a;GitHub - Guaishou74851/SCNet: Self-Supervised Scalable Deep Comp…

使用elementUI实现表格行拖拽改变顺序,无需引入外部库

前言&#xff1a; 使用vue2element UI&#xff0c;且完全使用原生的拖拽事件,无需引入外部库。 如果表格数据量较大&#xff0c;或需要更多复杂功能&#xff0c;可以考虑使用 vuedraggable库&#xff0c;提供更多配置选项和拖拽功能。 思路&#xff1a; 1. 通过el-table的ro…

深入理解接口测试:实用指南与最佳实践5.0(三)

✨博客主页&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客内容》&#xff1a;.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 &#x1f4e2;博客专栏&#xff1a; https://blog.csdn.net/m0_63815035/cat…

32位、64位、x86与x64:深入解析计算机架构

目录 一、32位架构(x86) 1.1 定义与历史 1.2 技术特点 1.3 优缺点 二、64位架构(x64) 2.1 定义与历史 2.2 技术特点 2.3 优缺点 三、x86与x64的关系 四、应用场景 4.1 32位架构的应用场景 4.2 64位架构的应用场景 五、总结 在计算机领域中,处理器架构的选择对…

【stable diffusion部署】超强AI绘画Stable Diffusion,本地部署使用教程,完全免费使用

前言 01 软件介绍 Stable Diffusion和Midjourney类似&#xff0c;都是当下AI绘画最流行的AI工具之一&#xff0c;都支持用文字生成AI图片或者图片生成图片的软件。 二者的区别是&#xff1a;Midjourney只能在网上使用&#xff0c;国内需要魔法才能使用&#xff0c;而且存在使…

【计算机网络】【网络层】【习题】

计算机网络-传输层-习题 文章目录 13. 图 4-69 给出了距离-向量协议工作过程&#xff0c;表&#xff08;a&#xff09;是路由表 R1 初始的路由表&#xff0c;表&#xff08;b&#xff09;是相邻路由器 R2 传送来的路由表。请写出 R1 更新后的路由表&#xff08;c&#xff09;。…

【嵌入式开发】单片机CAN配置详解

0 前言 CAN外设作为一种传输速率较高&#xff0c;且连线较为简洁的通信协议&#xff0c;如今很多单片机内部都集成了CAN控制模块&#xff0c;这样只需要再外接一个CAN收发芯片&#xff0c;将TTL/CMOS电平转换成CAN协议的差分电平&#xff0c;就是一个完整的CAN收发节点。   最…

虚拟机安装Ubuntu 24.04服务器版(命令行版)

这个是专门用于服务器使用的&#xff0c;没有GUI&#xff0c;常用软件安装&#xff0c;见 虚拟机安装Ubuntu 24.04及其常用软件(2024.7)_ubuntu24.04-CSDN博客https://blog.csdn.net/weixin_42173947/article/details/140335522这里只记录独特的安装步骤 1 下载Ubuntu 24.04安…

ctfshow-web入门-SSTI(web361-web368)上

目录 1、web361 2、web362 3、web363 4、web364 5、web365 6、web366 7、web367 8、web368 1、web361 测试一下存在 SSTI 注入 方法很多 &#xff08;1&#xff09;使用子类可以直接调用的函数来打 payload1&#xff1a; ?name{{.__class__.__base__.__subclasses__…

Axure网络短剧APP端原型图,竖屏微剧视频模版40页

作品概况 页面数量&#xff1a;共 40 页 使用软件&#xff1a;Axure RP 9 及以上&#xff0c;非软件无源码 适用领域&#xff1a;短剧、微短剧、竖屏视频 作品特色 本作品为网络短剧APP的Axure原型设计图&#xff0c;定位属于免费短剧软件&#xff0c;类似红果短剧、河马剧场…

如何从头开始构建神经网络?(附教程)

随着流行的深度学习框架的出现&#xff0c;如 TensorFlow、Keras、PyTorch 以及其他类似库&#xff0c;学习神经网络对于新手来说变得更加便捷。虽然这些框架可以让你在几分钟内解决最复杂的计算任务&#xff0c;但它们并不要求你理解背后所有需求的核心概念和直觉。如果你知道…

JS 实现SSE通讯和了解SSE通讯

SSE 介绍&#xff1a; Server-Sent Events&#xff08;SSE&#xff09;是一种用于实现服务器向客户端实时推送数据的Web技术。与传统的轮询和长轮询相比&#xff0c;SSE提供了更高效和实时的数据推送机制。 SSE基于HTTP协议&#xff0c;允许服务器将数据以事件流&#xff08;…