c语言进阶部分详解(详细解析自定义类型——结构体,内存对齐,位段)
上篇文章介绍了一些常用的字符串函数,大家可以去我的主页进行浏览。
各种源码大家可以去我的github主页进行查找:Nerosts/just-a-try: 学习c语言的过程、真 (github.com)
今天要介绍的是:结构体的相关内容
目录
一.结构体类型的声明
1.结构的基础知识
2.结构的声明
3.特殊的声明
4.结构的自引用
5.结构体变量的定义和初始化
6.结构体传参
二.结构体内存对齐
1.对其规则
2.存在原因
3.减少浪费
编辑
4.修改默认对齐数
三.位段
1.什么是位段
2.位段的内存分配
3.位段的跨平台问题
一.结构体类型的声明
1.结构的基础知识
结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量
2.结构的声明
结构的声明的原型:
struct tag{member - list ;} variable - list ;
eg:
struct Student
{char name[20];//名字int age;//年龄char sex[5];//性别char id[20];//学号
}; //分号不能丢
3.特殊的声明
匿名结构体:
struct
{int a;char b;float c;
}x;struct
{int a;char b;float c;
}a[20], *p;
4.结构的自引用
我们也许回想在结构中包含一个类型为该结构本身的成员是否可以呢?像下面这样
struct Node
{struct Node a1;int date[2];
};
这种情况下,需要确保结构体类型的定义是在使用它的结构体类型之前。否则,编译器将无法确定结构体类型的大小。
所以是不行的,正确的自引用方式如下:
struct Node
{int data;struct Node* next;
};
注意:
typedef struct {int data;Node* next; }Node;在定义指针变量next时,使用了Node类型。由于Node类型的定义在当前代码中尚未完成,编译器无法识别Node类型
正确的如下:
typedef struct Node {int data;struct Node* next; }Node;
5.结构体变量的定义和初始化
struct Point
{int x;int y;
}p1; //声明结构体的同时定义变量p1struct Point p2; //定义结构体变量p2
//也可以
struct Point p3 = {x, y};//初始化:定义变量的同时赋初值。struct Stu //类型声明
{char name[15];//名字int age; //年龄
};
struct Stu s = {"zhangsan", 20};//初始化
struct Node
{int data;struct Point p;struct Node* next;
}n1 = {10, {4,5}, NULL}; //声明结构体的同时嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//单独结构体嵌套初始化
6.结构体传参
struct S
{int data[1000];int num;
};
struct S s = { {1,2,3,4}, 1000 };
//结构体传参
void print1(struct S s)
{printf("%d\n", s.num);printf("%d\n", s.data[0]);printf("%d\n", s.data[1]);printf("%d\n", s.data[2]);
}
//结构体地址传参
void print2(struct S* ps)
{printf("%d\n", ps->num);printf("%d\n", ps->data[0]);printf("%d\n", ps->data[1]);printf("%d\n", ps->data[2]);
}
int main()
{print1(s); //传结构体变量printf("_________");print2(&s); //传地址return 0;
}
两种调用,传参的结果都是一样的:
但是,还是用printf2来传地址时更好:
函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。如果传递一个结构体对象的时候, 结构体过大,参数压栈的的系统开销比较大 ,所以会导致性能的下降
二.结构体内存对齐
struct S1{char c1 ;int i ;char c2 ;}; 这个结构体有多大呢?第一反应大抵是:1+4+1=6吧
但其实:

1.对其规则
1. 第一个成员在与结构体变量偏移量为 0 的地址处。2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数 = 编译器默认的一个对齐数 与 该成员大小的 较小值 。 VS中默认的值为83. 结构体 总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍 。4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
按照对其规则,这是上述答案的分析:
接下来再看另外一个例子:
eg:
struct S2
{char c1;char c2;int i;
};int main()
{printf("%d", sizeof(struct S2));return 0;
}

答案便是:
2.存在原因
结构体的内存对齐是拿空间来换取时间的做法
一些资料也显示说:
- 访问效率:内存对齐可以使结构体的成员在内存中连续存储,减少内存访问次数,提高访问效率。如果结构体成员没有进行内存对齐,可能会导致成员之间存在空隙,需要多次访问内存才能获取到所有成员的值
- 数据对齐:某些硬件平台要求访问特定类型的数据必须按照特定字节对齐,否则可能会导致访问错误或性能下降。例如,某些处理器要求访问双字节数据(如short类型)必须按2字节对齐,访问四字节数据(如int类型)必须按4字节对齐。如果结构体成员没有进行内存对齐,可能会导致访问错误或性能下降

3.减少浪费
那我们如何尽量减少内存对齐所产生的浪费呢?
让占用 空间小的成员尽量集中 在一起
所以上述S1的例子我们可以改造成:
struct S1
{char c1;int i;char c2;
};
struct S2
{char c1;char c2;int i;
};
int main()
{printf("%d\n", sizeof(struct S1));printf("%d", sizeof(struct S2));return 0;
}
结果也确实减小了内存使用:
4.修改默认对齐数
这里我们使用#pragma,可以改变我们的默认对齐数
#pragma pack(8)//设置默认对齐数为8
struct S1
{char c1;int i;char c2;
};#pragma pack()//取消设置的默认对齐数,还原为默认
#pragma pack(1)//设置默认对齐数为1
struct S2
{char c1;int i;char c2;
};int main()
{printf("%d\n", sizeof(struct S1));printf("%d", sizeof(struct S2));return 0;
}
这次S2的大小便是我们最初认为的6了:

三.位段
1.什么是位段
位段的声明和结构是类似的,有两个不同:
- 位段的成员必须是 int、unsigned int 或signed int 。
- 位段的成员名后边有一个冒号和一个数字
struct A {int a : 2; //a占用2个bit位int b : 5; //b占用5个bit位int c : 10;int d : 30;
};int main()
{struct A a;printf("%d", sizeof(a));
}
不使用位段的话是占16个字节,现在是:
2.位段的内存分配
- 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型
- 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的(一次增加4/1个字节)
- 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段
struct S
{char a : 3;char b : 4;char c : 5;char d : 4;
};int main()
{struct S s = { 0 };s.a = 10;s.b = 12;s.c = 3;s.d = 4;return 0;
}

3.位段的跨平台问题
- int 位段被当成有符号数还是无符号数是不确定的。
- 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题。
- 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
- 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是 舍弃剩余的位还是利用,这是不确定
这次关于结构体相关的内容就先到这里啦! 在下一篇文章中,我们将详细介绍枚举和联合体的内容。感谢大家的支持,加油!!!
相关文章:
c语言进阶部分详解(详细解析自定义类型——结构体,内存对齐,位段)
上篇文章介绍了一些常用的字符串函数,大家可以去我的主页进行浏览。 各种源码大家可以去我的github主页进行查找:Nerosts/just-a-try: 学习c语言的过程、真 (github.com) 今天要介绍的是:结构体的相关内容 目录 一.结构体类型的声明 1.…...
Mysql第三篇---响应太慢?数据库卡顿?如何优化?
Mysql第三篇—响应太慢?数据库卡顿?如何优化? 统计SQL的查询成本:last_query_cost 一条SQL查询语句在执行前需要确定查询执行计划,如果存在多种执行计划的话,MySQL会计算每个执行计划所需要的成本&#x…...
【计算机网络】HTTP 协议的基本格式以及 fiddler 的用法
HTTP协议的基本格式如下: 1.请求行: 包括请求THHP协议的版本、请求URI(资源路径)和HTTP方法(如GET、POST、PUT、DELETE等) GET/example.html HTTP/1.1 GET表示请求方法,/example.html表示请求的…...
人大金仓与哪吒科技达成战略合作,加快推动智慧港口建设
近日,人大金仓与哪吒港航智慧科技(上海)有限公司(以下简称“哪吒科技”)达成战略合作。双方旨在共享优势资源,联合为港口企业转型升级提供完备的技术支撑与行业解决方案。人大金仓总裁杜胜、哪吒科技总经理…...
FFmpeg工具使用集
FFmpeg工具使用集 About FFmpeg Java调用FFmpeg FFmpeg 工具: FFMPEG 用于转换多媒体文件的 命令行工具 格式之间( ffmpeg\bin\ffmpeg.exe ) ffplay 基于 SDL 和 FFmpeg 库的简单媒体播放器 ( ffmpeg\bin\ffplay.exe ࿰…...
2024级199管理类联考之英语二2200核心词汇(第一天)
define 下定义,定范围definition 定义,清晰度identify 鉴定,识别,确认identifiable 可识别的,可辨认的identity 身份,一致determine 决心,确定determinism 宿命论,决定论judge 判断,法官/裁判behavior 举止,表现behavioral 行为的conduct v-实施,引导,指挥; n-实施方式,行为,举…...
webGL编程指南 第三章 平移三角形 TranslatedTriangle.js
我会持续更新关于wegl的编程指南中的代码。 当前的代码不会使用书中的缩写,每一步都是会展开写。希望能给后来学习的一些帮助 git代码地址 接着 上一节 接着做平移的转化。在本次的案例案例中主要是xy的坐标变量相加,同时传递个给相关变量 <!DOCTY…...
推荐一款支持异步批量下载图片的chrome插件——图片助手(ImageAssistant) 批量图片下载器
https://chrome.google.com/webstore/detail/imageassistant-batch-imag/dbjbempljhcmhlfpfacalomonjpalpko/related?hlzh-CNhttps://chrome.google.com/webstore/detail/imageassistant-batch-imag/dbjbempljhcmhlfpfacalomonjpalpko/related?hlzh-CN 安装后直接点击 会根据…...
vue 动态数字效果 vue-animate-number
安装 vue-animate-number 插件 npm install vue-animate-number (注:是npm、cnpm还是yarn根据具体项目要求) 在 main.js 中引入 import Vue from vue import VueAnimateNumber from vue-animate-number Vue.use(VueAnimateNumber)动态使用…...
10月22日,每日信息差
今天是2023年10月22日,以下是为您准备的13条信息差 第一、库迪咖啡计划到2025年底全球门店数量达2万家,库迪咖啡开业一周年全球门店数量达到6061家,位居全球第四 第二、超高速纯硅调制器取得创纪录突破,国际上首次把纯硅调制器带…...
Android系统之SurfaceFlinger
参考资料: Android 显示系统:SurfaceFlinger详解 Android 渲染机制——SurfaceFlinger 一篇文章看明白 Android 图形系统 Surface 与 SurfaceFlinger 之间的关系 Android卡顿原理分析和SurfaceFlinger,Surface概念简述 Android Graphics…...
jQuery实现输入框提示并点击回显功能呢
html代码: <input type"text" id"affOrganization" name"affOrganization" class"form-control" placeholder"Search..." style"width: 300px" > <div class"search_suggest" id"gov_se…...
终端常用操作
终端操作 取消 可以用ctrl c,不要一个一个删除,会取消掉开新的一行回溯上一次的命令,ctrl r,然后键入关键词,直接回车运行就行 chmod x 文件名 给某个文件运行需要的权限。...
JWFD开源工作流矩阵引擎测试版本BUG20231022修正代码
public void ParamFileOutputValue(String paramfile) {String s "";String sp "";String ssp "";List<String> list new ArrayList<String>();int p 0;int k 0;//这个地方要修改为整个参数表的最大行数,而不是起始…...
分拣设备运动仿真
这一次我们来分享一下如何在Solidworks 中做出传送台的分拣动作并通过分拣动作生成过程动画,以便于我们可以用于产品展示又或者验证运行程序无误的情况下结构是否会影响输送效率。 首先创建一个新的运动算例 将窗口切换至Motion分析 在设置之前我们先理清设置传送带…...
Python【列表的反转与排序】
目录 要求:列表的反转 列表的排序 列表的反转: 方案一:使用reverse()方法:它会直接修改原始列表,进行反转。 方案二:还是使用reversed()函数:该函数返回一个反转后的迭代器对象,…...
2 用TensorFlow构建一个简单的神经网络
上一篇:1 如何入门TensorFlow-CSDN博客 1、环境搭建 后续介绍的相关代码都是在pycharm运行,pycharm安装略。 打开pycharm,创建一个新的项目用于tensorflow编码练习,在Terminal输入命令: # 依赖最新版本的pip pip i…...
快手视频批量下载.py(10月可以用)
完整代码如下: # _*_ coding:utf-8 _*_# _*_ coding:utf-8 _*_import json import requests import time import randomheaders = """Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6 Con…...
如何用工业树莓派和MQTT平台打通OT和IT?
一、应用设备 OT端设备:步进电机,MODBUS TCP远程I/O模块,PLC设备 边缘侧设备:宏集工业树莓派; IT端设备:PC、安卓手机; IT端软件:宏集HiveMQ MQTT通信平台 二、原理 宏集工业树…...
大模型背景下软件工程的机遇与挑战
点击链接了解详情 本文作者:汪晟杰 导语:AISE(AI Software Engineering)有人说是软件工程 3.0,即基于大模型(LLM - Large Language Model)时代下的软件工程。那么究竟什么是 AISE,他的发展历程对…...
如何快速上手w64devkit:面向开发者的轻量级跨平台编译指南
如何快速上手w64devkit:面向开发者的轻量级跨平台编译指南 【免费下载链接】w64devkit Portable C and C Development Kit for x64 (and x86) Windows 项目地址: https://gitcode.com/gh_mirrors/w6/w64devkit w64devkit是一个专为Windows平台设计的轻量级C和…...
为什么EuroSAT成为遥感图像分类的黄金标准?
为什么EuroSAT成为遥感图像分类的黄金标准? 【免费下载链接】EuroSAT EuroSAT: Land Use and Land Cover Classification with Sentinel-2 项目地址: https://gitcode.com/gh_mirrors/eu/EuroSAT 在人工智能与地球观测技术融合的时代,遥感图像分类…...
ABAP BAPI_PO_CREATE1实战:如何绕过信息记录直接设置PO净价(附代码示例)
ABAP BAPI_PO_CREATE1深度实战:绕过信息记录精准控制采购订单价格的五种策略 在SAP采购订单创建过程中,信息记录(Info Record)中的价格通常会作为默认值自动带出,但实际业务场景往往需要更灵活的价格控制。当遇到特殊采…...
手把手教你用Qwen3-TTS:10种语言语音合成,开箱即用
手把手教你用Qwen3-TTS:10种语言语音合成,开箱即用 1. 为什么选择Qwen3-TTS? 想象一下,你正在开发一个多语言智能客服系统,需要为不同国家的用户提供自然流畅的语音服务。传统方案可能需要部署多个语音合成引擎&…...
ANIMATEDIFF PRO新手必看:简单三步,用文字生成高质量动态GIF
ANIMATEDIFF PRO新手必看:简单三步,用文字生成高质量动态GIF 1. 从文字到动态影像的魔法 想象一下,你只需要输入一段文字描述,就能在短短25秒内获得一段16帧的电影级动态GIF。这不是科幻电影的情节,而是ANIMATEDIFF …...
函数信号发生器在电路调试中的实战技巧
1. 函数信号发生器的核心功能解析 第一次接触函数信号发生器时,我盯着面板上密密麻麻的按钮发懵。这玩意儿不就是个能发出"滴滴"声的高级玩具吗?直到有次调试音频电路,用正弦波发现放大器在特定频率出现削顶失真,才真正…...
CHORD-X代码生成能力展示:根据研报结论自动输出数据分析脚本
CHORD-X代码生成能力展示:根据研报结论自动输出数据分析脚本 最近在试用一个挺有意思的模型,叫CHORD-X。大家可能知道它在文本生成、对话方面挺强的,但我发现它还有个隐藏技能,或者说一个特别实用的能力延伸——它能看懂你写的分…...
Ollama本地大模型新玩法:PasteMD剪贴板美化工具深度体验
Ollama本地大模型新玩法:PasteMD剪贴板美化工具深度体验 1. 为什么PasteMD是文本处理的革命性工具 在日常工作中,我们经常遇到这样的困扰: 从会议录音转写的文字稿杂乱无章,关键信息淹没在大量口语化表达中复制粘贴的代码片段丢失…...
434649494
4546465484...
MATLAB梯度计算与三维箭头绘制:gradient函数配合quiver3的完整指南
MATLAB梯度计算与三维箭头绘制:gradient函数配合quiver3的完整指南 在科学计算与工程仿真领域,三维向量场的可视化是理解复杂数据分布的关键技术。无论是电磁场强度分布、流体力学中的速度场,还是机械结构中的应力场,都需要直观呈…...

