0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何设计只有数据字段的结构体

开关电源芯片 来源:程序喵大人 作者:程序喵大人 2021-08-23 09:37 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

之前写过一篇《如何设计一个C++的类》,今天这里继续聊聊如何设计结构体,注意本文不介绍在C++中结构体和类具体有什么区别,本文所说的结构体是指只有数据字段不带任何函数的那种结构体。

当创建结构体的实例时,结构体的数据成员会按其声明的顺序连续存储。然而,这个声明的顺序也是有学问的,顺序不同结构体的大小可能有很大差别,数据成员的访问性能也可能会有很大区别!

这里涉及一个概念:内存对齐。关于内存对齐我之前写过一篇文章:《内存对齐》,这里不深入讨论,只是简单介绍一下。

大多数编译器会对齐数据成员,会以四舍五入地址方式来优化数据的访问,如下表所示。

0c708e52-02f8-11ec-9bcf-12bb97331649.jpg

这种内存对齐可能会在成员大小混合的结构体中产生未使用字节的空洞。

例如:

struct S {

short int a; // 2字节

// 6个空洞

double b; // 8

int d; // 4

// 4个空洞

};

S ArrayOfStructures[100];

这里,在a和b之间有6个未使用的字节,因为b必须从一个能被8整除的地址开始。

最后还有4个未使用的字节空洞。这样做的原因是,数组中S的下一个实例必须从一个能被8整除的地址开始,以便将其b成员以8对齐。

然而,如果改变一下结构体中数据成员声明的顺序,通过将最小的成员放在最后,未使用的字节数可以减少到2:

struct S {

double b; // 8

int d; // 4

short int a; // 2

// 2个空洞

};

S ArrayOfStructures[100];

这种重新排序使结构体变小了8个字节,那整个数组则变小了800个字节。

在此特性上,类和结构体相同。通过重新排序数据成员,结构体对象和类对象通常可以变得更小。如果类至少有一个虚成员函数,则在第一个数据成员之前或最后一个成员之后会有一个指向虚函数表的指针。该指针在32位系统中为4字节,在64位系统中为8字节。

如果不确定结构体或它的每个成员有多大,可以使用sizeof操作符进行一些测试。sizeof操作符返回的值包括对象末尾的任何未使用的字节(内存对齐后的字节数)。

还有一个知识点:

如果数据成员相对于结构体或类开头的偏移量小于128,则访问数据成员的代码会更加紧凑,因为该偏移量可以使用8位有符号的数字来表示。如果相对于结构体或类的开头的偏移量是128字节或更多,那么偏移量必须表示为一个32位数字(指令集在8位到32位之间没有偏移量)。例如:

struct S {

int a[100]; // 400

int b; // 4

int read() { return b; }

};

b成员的偏移量是400。任何通过指针或成员函数访问b字段的代码都需要将偏移量编码为32位数字。如果交换a和b,则两者都可以通过编码为8位有符号数字的偏移量来访问,或者根本不需要偏移量。

这会使代码更紧凑,方便更有效地使用代码缓存。因此,建议在结构或类声明中,大数组和其他大对象排在最后,最常用的数据成员排在前面。如果不能在前128个字节内包含所有数据成员,则将最常用的成员放在前128个字节中。

通过上面两个小知识点可以使得将结构体设计的更小,访问数据成员的速度更快,但是这有时往往会牺牲一些可读性,比如这种结构体:

struct S {

int deskA;

double deskB;

bool deskC;

int chairA;

double chairB;

bool chairC;

};

可能这样修改后结构体会更小:

struct S {

int deskA;

int chairA;

double deskB;

double chairB;

bool deskC;

bool chairC;

};

但是我们一般情况下貌似希望同类的字段放在一起,这样代码可读性更高一些,易于读懂代码。至于这种结构体具体需不需要重新排序,那就需要大家自己权衡啦。

小总结:

注意内存对齐;

128是个槛,常用的数据成员可考虑放在前128字节中,不常用的或大的数据成员可考虑放在后面;

注重性能优化的同时也需要权衡一下代码的可读性。

打完收工。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 存储器
    +关注

    关注

    39

    文章

    7715

    浏览量

    170856
  • 内存
    +关注

    关注

    9

    文章

    3173

    浏览量

    76115
  • 结构体
    +关注

    关注

    1

    文章

    131

    浏览量

    11300

原文标题:如何设计结构体

文章出处:【微信号:gh_3980db2283cd,微信公众号:开关电源芯片】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    typedef结构使用

    虽然结构的出现能够让我们有一个更科学的数据结构来管理数据,但是每次使用结构都需要struct
    发表于 12-08 07:04

    为什么不建议用匿名结构

    说起匿名结构,想必大家第一感觉就是看着好高大上的名字,但实际上也就那样。 typedef struct { union { struct { uint8_t bit_0:1
    发表于 12-04 07:39

    modbus消息帧的模块化架构介绍

    01/02/03/04 读取线圈/输入/保持寄存器 数据写入 05/06/15/16 写入单个/多个寄存器 诊断类 08/0B/0E 设备诊断/异常报告 3. 数据字段:操作参数的载体 数据字段
    发表于 11-17 08:15

    C语言结构使用

    有时候需要将不同类型的数据组合为一个整体,以便于引用。例如,一名学生有学号、姓名、性别、年龄等属性,如果针对每个属性都单独定义一个变量,那么当有多名学生时变量就难以分清。结构就是用来管理不同类
    发表于 11-12 08:30

    NVMe高速传输之摆脱XDMA设计20: PCIe应答模块设计

    所示。图1TLP写处理模块结构图当axis_cq总线中出现数据流传输时,应答模块首先对传输的TLP报头的类型字段进行解析,如果为存储器写请求则由写处理模块进一步解析。写处理模块提取出TLP报头的地址
    发表于 08-12 16:04

    NVMe高速传输之摆脱XDMA设计14: PCIe应答模块设计

    如图1所示。 图1TLP写处理模块结构图 当axis_cq总线中出现数据流传输时,应答模块首先对传输的TLP报头的类型字段进行解析,如果为存储器写请求则由写处理模块进一步解析。写处理模块提取
    发表于 08-04 16:44

    定义IO初始化结构

    由上述IOPORT相关功能的枚举类型我们可以知道,在对IOPORT模块进行初始化时需要根据情况配置它们。因此我们定义一个IOPORT初始化的结构类型IOPORT_Init_t,它的成员包括了由上述所有枚举类型所声明的变量,因此该结构
    的头像 发表于 07-16 16:26 1108次阅读

    智能AI面临非结构数据难题:IBM推出解决方案

    ,同时提供一个开放的混合数据基础架构和企业级的结构化和非结构数据管理。 智能AI面临非结构
    的头像 发表于 07-02 09:40 389次阅读

    渗压计在混凝土结构中的安装指南

    在现代土木工程和岩土工程中,渗压计是监测混凝土结构体内孔隙水压力变化的重要工具。南京峟思公司生产的渗压计因其高精度和可靠性而被广泛应用于各种工程监测项目中。一、渗压计在混凝土结构中的应用价值渗压计
    的头像 发表于 05-28 10:55 383次阅读
    渗压计在混凝土<b class='flag-5'>结构</b><b class='flag-5'>体</b>中的安装指南

    使用USB控制中心通过FX3将数据传输到DSP,数据字丢失怎么解决?

    使用传输文件-输出功能时, DMABuf1[0] 中的第一个数据字错误地为 0x0000,最后一个数据字 0x27FF 丢失。 有趣的是,如果我重新发送同一个文件,收到的第一个单词就是之前丢失
    发表于 05-21 07:31

    程序设计与数据结构

    《程序设计与数据结构》重点阐述了三大方向内容: 1. C语言学习中的痛点:针对当前工程师在C语言学习中的痛点,如指针函数与函数指针,如何灵活应用结构等。从变量的三要素(变量的类型,变量的值和变量
    发表于 05-13 16:45

    C语言中结构与联合体的深度解析:内存布局与应用场景

    一、基础概念与核心差异 1.1 结构(Struct)的本质 **结构是C语言中实现数据封装的基石,其核心特征在于内存独立性。每个成员变量
    发表于 04-08 09:18

    ADS1293在中断采用Stream mode读取数据数据字节数不对是哪里出了问题?

    mode读取数据(按照datasheet33页的介绍做的),发现数据字节数不对,后用示波器测量此时DRDYB管脚变成200Hz方波了; 3、使用的配置DRDYB_SRC_REG(地址0x27)的值是0x08, CH_CNFG_REG(地址0x2F)值是0x70。 不知道
    发表于 01-13 08:32

    LDC1000 Frequency Data只有最低数据有数据其他2位都是0x00,为什么?

    Frequency Data只有最低数据有数据其他2位都是0x00,我想问下我这问题出在哪里?我的参数设置: RpMAX=0x13;//21.547 RpMIN=0x3d; //1.347
    发表于 01-06 07:33

    ADS5547, DAC8822时序图上只有数据在寄存器之间转换的时序,难道更新速率只和数据在寄存器之间转换时间有关吗?

    ADS5547, DAC8822时序图上只有数据在寄存器之间转换的时序,难道更新速率只和数据在寄存器之间转换时间有关吗?
    发表于 12-20 07:28