63.【C语言】再议结构体(上)

news2024/9/28 21:24:41

1.复习

20.【C语言】初识结构体(重要)

48.【C语言】结构体补充

2.结构体的特殊声明

01.匿名结构体

*定义

不完全声明,即结构体没有自己的名字(没有结构体标签)

*注意事项

1.匿名结构体只能使用一次

2.下列代码合法吗
struct
{
	int a;
	char b;
	float c;
}x;

struct
{
	int a;
	char b;
	float c;
}*p;

int main()
{
	p = &x;
	return 0;
}

虽然编译没有问题 ,但生成解决方案会报警告

 warning C4133: “=”: 从“*”到“*”的类型不兼容

编译器认为:x;和*p;是两个不同的结构体

02.自引用

前置知识

*数据结构:数据在内存中的存储结构

*常见的数据结构:数组,记录,链表

*一个典型的数据结构----链表:一种物理存储单元上非连续(因为用了指针)、非顺序(因为用了指针)的存储结构,用于线性方式存储数据(对比数组:元素的顺序集合)

下面这张图(摘自《计算机科学导论》)体现非顺序65-->66-->72-->96-->85-->74

*链表中的每一个元素称为结点,结点包含两个部分:数据和链(链是下一个节点的地址(指针),指向下一个节点的数据),链最后一个元素包含一个空指针

*链表名是头指针的名字,下面这张图(摘自《计算机科学导论》)

《计算机科学导论》对链表的解释


单向链表图例

代码实现链表的一个结点

struct Node
{
    int data = 0;//数据
    struct Node* next;//链(地址)(指针)
};

注:Node n.节点,结点

运行上方代码,x86环境下在内存中查看结构体

typedef重命名结构体

禁止使用typedef重命名匿名结构体

typedef struct Node
{
    int data;
    struct Node* next;
}Node;

3. 结构体内存对齐(考频高)

如果看过李忠老师的《x86汇编语言:从实模式到保护模式 第二版》将会比较好理解

8086CPU的内存对齐方式

书中提到:8086CPU在存储数据段时采用16字节对齐的方式,如果定义的数据没有到16字节的整数倍,将以00填充满

例如:

db "Hello"
db "World!"

在内存中查看数据的排布:

设该字符串有x个字符(即x bytes)

其在内存中的存储占用的字节数S的公式:

① x ≦ 16,S=16

②x = 16k (k为正整数),S=16k

③  16k<x ≦16(k+1) (k为正整数),S=16(k+1)

对于结构体来说,内存对齐有4条规则

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

2. 其他成员变量(即从第二个成员变量开始)要对齐到某个数字(对齐数)的整数倍的地址处

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

    对齐数要看偏移量

           -->VS中默认的值为8 bytes

           -->Linux中gcc没有默认对齐数,对齐数就是成员自身的大小

3. 结构体总大小(注意这里说的不是偏移量)为最大对齐数(结构体中每个成员变量(含第一个成员变量)都有一个对齐数,所有对齐数中最大的)的整数倍,这样可能会浪费一些空间

4.如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。

例题:非嵌套结构体

求下列代码的执行结果(在VS2022中测试)

#include <stdio.h>
struct s1
{
	char a;
	char b;
	int c;
};

struct s2
{
	char a;
	int c;
	char b;
};

int main()
{
	printf("%zd,%zd", sizeof(struct s1), sizeof(struct s2));
	return 0;
}

提示:结构体s1和结构体 s2唯一不同的地方在成员变量的排列顺序

s1:①char a ②char b ③int c

s2:①char a ②int c ③char b

 答案速查

分析

在3.【C语言】内置数据类型文中讲过char占1个字节,int占4个字节

由内存对齐有4条规则可以画图(设CPU为结构体从偏移量为0处开辟空间):

对于结构体s1

1 < 8,a的对齐数为1

4 < 8,c的对齐数为4

从偏移量0到偏移量7,一共占8个字节,为最大对齐数4的整数倍(对齐数1 < 对齐数4)

因此sizeof(struct s1) == 8

对于结构体s2

c存储的位置必须从偏移量为4的最近位置开始

存储完a,c,b后,8-0+1=9 bytes,不是最大对齐数4的整数倍,因此要至偏移量为11的位置

因此打印结果为8,12

练习

求下列代码的执行结果(在VS2022中测试)

#include <stdio.h>
struct s3
{
	double d;
	char c;
	int i;
};

int main()
{
	printf("%zd", sizeof(struct s3));
	return 0;
}

答案速查

分析

例题:嵌套结构体

求下列代码的执行结果(在VS2022中测试)

#include <stdio.h>
struct s3
{
	double d;
	char c;
	int i;
};

struct s4
{
	char c1;
	struct s3 s3;
	double d;
};

int main()
{
    struct s4 s4;
	printf("%zd", sizeof(struct s4));
	return 0;
}

答案速查

分析

结构体的整体大小就是所有最大对齐数的整数倍(s3的最大对齐数和s4的最大对齐数都是8)

4.内存对齐的原因

1. 平台原因(移植原因)
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常
2. 性能原因
数据结构(尤其是栈)应该尽可能地在自然边界上对齐.原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问.假设一个处理器总是从内存中取8个字节,则地址必须是8的倍数.如果我们能保证将所有的double类型的数据的地址都对齐成8的倍数,那么就可以用一个内存操作来读或者写值了.否则,我们可能需要执行两次内存访问,因为对象可能被分放在两个8字节内存块中
总体来说:结构体的内存对齐是拿空间来换取时间的做法

5.内存对齐节省空间的方法

让占用空间小的成员尽量集中在一起

例如:

struct S1
{
	char c1;
	int i;
	char c2;
};
struct S2
{
	char c1;
	char c2;
	int i;
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用python获取百度一下,热搜TOP数据详情

一、查找对应链接 # 警告&#xff1a;以下代码仅供学习和交流使用&#xff0c;严禁用于任何违法活动。 # 本代码旨在帮助理解和学习编程概念&#xff0c;不得用于侵犯他人权益或违反法律法规的行为。 1、打开百度页面 百度一下&#xff0c;你就知道 2、点击F12 或 右键鼠标…

text2sql方法:NatSQL和DIN-SQL

NatSQL NatSQL出自2021年9月的论文《Natural SQL: Making SQL Easier to Infer from Natural Language Specifications》(github)&#xff0c;它是一种SQL 中间表征(SQL intermediate representation(IR))方法。 NatSQL作者认为Text2SQL的关键挑战是自然语言描述和其对应的SQ…

Cookie、Session、Token(JWT)还不懂?

Cookie、Session、Token&#xff08;JWT&#xff09; 三者的区别与用途&#xff01;如何进行身份认证&#xff0c;保持用户登录状态&#xff1f; Cookie、Session 和 Token 都是在 Web 开发中用于管理用户状态和进行身份认证的技术&#xff0c;它们之间有以下区别和用途&#…

【js逆向学习】酷我音乐排行榜 python+nodejs(webpack)

逆向目标 目标网址: https://www.kuwo.cn/rankList目标接口: https://www.kuwo.cn/api/www/bang/bang/musicList 加密参数: 参数一&#xff1a;secret参数二&#xff1a;reqId 逆向过程 老规矩先分析网络请求&#xff0c;我们可以分析到网络请求是通过ajax进行的&#xff…

【C++】C/C++内存管理(new/delete)

C/C内存分布 代码内存相关问题 int globalVar 1; static int staticGlobalVar 1;void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";const char* pChar3 "abcd";int* ptr1 (int*)malloc(siz…

yolox训练自己的数据集

环境搭建 gpu按自己情况安装 nvidia-smi 查看自己的版本 CUDA和cudnn 按自己的安装&#xff0c;我的驱动551.76&#xff0c;注意不要用最新的&#xff0c;官网只要求驱动是大于等于&#xff0c;可以用低版本的cuda&#xff0c;我安装的是CUDA 11.1 cuda下载后&#xff0c…

报告查询系统小程序开发制作方案

报告查询小程序系统主要是为了解决传统报告查询方式往往依赖于纸质文档或复杂的内网系统&#xff0c;存在查询效率低、信息更新慢、携带不便等问题。 一、目标用户 企业员工&#xff1a;需要频繁查询各类工作报告&#xff0c;如销售人员查询销售业绩报告&#xff0c;财务人员查…

信道衰落的公式

对于天线&#xff1a; 对于天线的面积计算&#xff1a; 天线的接收功率密度&#xff1a; 天线的接收功率&#xff1a; 移动无线信道&#xff08;I&#xff09; (xidian.edu.cn)https://web.xidian.edu.cn/zma/files/20150710_153736.pdf 更加常用的考虑了额外的信道衰落pathlo…

基于YOLOv5的农作物病虫害识别系统设计与实现(PYQT+web端+微信小程序+YOLOv5+训练数据集+论文+部署文档+开题报告)

摘要 农作物病虫害是农业生产中的关键问题&#xff0c;病虫害的爆发和侵袭不仅严重影响农作物产量和质量&#xff0c;还可引发局部地区严重的灾害性损失。因此&#xff0c;及时发现和预防农作物病虫害的发生和发展至关重要。本文以农作物病虫害图像为载体&#xff0c;运用深度…

python的高级用法

对于python的使用&#xff0c;我们常见的用法是python xx.py直接执行脚本&#xff0c;有时可能您需要在脚本的第一行添加&#xff08;#!/usr/bin/env python3 或 #!/usr/local/bin/python3&#xff09;&#xff0c;然后chmod确保脚本文件具有可执行权限。这样脚本就可以在终端直…

从哪里下载高清解压视频素材?推荐五个优质素材资源网站

想制作吸引人的抖音小说推文&#xff0c;但不知道从哪里获取高清解压视频素材&#xff1f;今天就为大家推荐五个优秀的网站&#xff0c;帮助你轻松找到所需的素材&#xff0c;提升你的创作质量。 首先是蛙学网 作为国内顶级的短视频素材网站&#xff0c;蛙学网提供了丰富的4K高…

Vxe UI vue 使用 vxe-tabs 页签实现右侧操作按钮、关闭所有页签、关闭右侧、关闭左侧

Vxe UI vue 使用 vxe-tabs 页签实现右侧操作按钮、关闭所有页签、关闭右侧、关闭左侧 查看 github <template><div><vxe-tabs v-model"selectTab" :options"tabList"><template #extra><vxe-pulldown :options"tabOptio…

Flood Fill模型

这个模型主要用来求连通块的数量&#xff0c;在求连通块时有“8连通”和“4连通”之分。 看上面的图形&#xff0c;如果是4连通那么红色和绿色就不连通&#xff08;只有一个格子的“上下左右”相连才叫连通&#xff09;。如果是8连通那就联通&#xff08;不仅仅包含边相连&…

SwiftUI简明概念(4):如何对shape同时进行fill和stroke

1、iOS17方案 iOS17上可以同时对shape调用fill和stroke&#xff1a; Circle().stroke(.red, lineWidth: 20).fill(.orange).frame(width: 150, height: 150) 效果也如我们所预料的&#xff1a; 而且stroke可以调用任意次&#xff1a; Circle().stroke(.blue, lineWidth: 45…

【路径规划】基于球向量的粒子群优化(SPSO)算法在无人机路径规划中的实现

摘要 本文介绍了基于球形矢量的粒子群优化&#xff08;Spherical Particle Swarm Optimization, SPSO&#xff09;算法&#xff0c;用于无人机&#xff08;UAV&#xff09;路径规划。SPSO算法通过引入球形矢量的概念&#xff0c;增强了粒子群在多维空间中的探索和利用能力&…

TXT文档批量处理,根据总行数平均分成多个文件保存,批量拆分实例分享

在高强度的工作下&#xff0c;怎样拆分文档&#xff0c;手动拆分整理&#xff0c;不仅效率低&#xff0c;而且还容易出错。当然是要选择操作轻松简单首助编辑高手&#xff0c;提高工作效率。 1、打开软件并选择到文本批量操作功能选项上&#xff0c;选择文本批量操作&#xff1…

【C++】类和对象(类的定义,类域,实例化,this指针)

目录 一. 类的定义 【对比c】结构体和类的区别 1. 称呼&#xff1a;变量 or 对象&#xff1f; 2. 类型&#xff1a; 3. 访问限定&#xff1a; 4. c和c结构体使用 5. 相同点&#xff1a; 二. 类域 三. 实例化 1. 1对N 2. 计算大小只考虑成员变量 3. 到此一游 四. …

一、前后端分离及drf的概念

1.1什么是前后端分离 程序角度 前后端不分离&#xff1a;一个程序&#xff08;如django),接收请求处理HTML模版用户返回 前后端分离&#xff1a;两个程序 --前端&#xff1a;vue.js/react.js/angular.js --后端&#xff1a;Django drf(django rest framework) 2.专业角度 --…

3.消息机制总结——总结

Handler 机制的底层逻辑就是利用 epoll eventfdAndroid2.3开始 Google把Handler的阻塞/唤醒方案从Object#wait()/notify(),改为Linux epoll实现&#xff0c;why&#xff1f;原因在于&#xff0c;native也引入了消息管理机制&#xff0c;用于提供个C/C开发者使用&#xff0c;而…

nicegui组件button用法深度解读,源代码IDE运行和调试通过

传奇开心果微博文系列 前言一、button 组件基本用法1. 最基本用法示例2. 创建带图标按钮 二、button按钮组件样式定制1. 按钮的尺寸调整2. 改变颜色示例3. 按钮的自定义字体大小4. 圆角形状示例5. 自定义边框6. 添加阴影7. 复合按钮8. 浮动按钮9. 可扩展浮动操作按钮QFAB10. 按…