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

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

    关注

    38

    文章

    7481

    浏览量

    163751
  • 内存
    +关注

    关注

    8

    文章

    3016

    浏览量

    73989
  • 结构体
    +关注

    关注

    1

    文章

    130

    浏览量

    10840

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

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

收藏 人收藏

    评论

    相关推荐

    ADS7953SDBTR上电时16个通道中,只有4个通道有数据,其余12个通道无数据,怎么解决?

    请教一下,我现在有用一个16通道的模数转换器ADS7953SDBTR,使用过程中出现了一个问题,第一次上电的时候只有4个通道有数据,其它12个通道没有数据,然后掉电重启,16个通道都正常了,检测了
    发表于 12-06 07:26

    结构成员的顺序会影响结构的大小吗

    相同的结构成员,如果把顺序调整一下,会不会影响结构的大小? 答案是会的,这主要跟字节对齐有关。 比如这样的结构
    的头像 发表于 11-25 16:24 140次阅读

    PCM1865-Q1在LRCK低电平时只有DOUT2有数据,DOUT没有数据,为什么?

    4.GPIO3 作为DOUT2接口 5.四个ADC通道,均采用单端输入方式, 现遇到问题如下: 如图:WS是LRCK,SCLK是BCK ,SDATA是DOUT , D14是DOUT2 具体问题是 在LRCK低电平时只有DOUT2有数据,DOUT没
    发表于 10-29 06:25

    TLV320aic3101的TDM设置,想用TDM采集所有数据,请问怎样设置?

    请教TLV320aic3101的TDM设置,现在我接了两路声音,一共4声道到一片TLV320aic3101,想用TDM采集所有数据,请问怎样设置?现在我已经打开了256-clock,发现只有其中
    发表于 10-24 07:34

    全国首批数据跨境场景化一般数据清单发布

    智能网联汽车行业中包括四大场景共23类数据类型及158项数据字段,具体包括跨国生产制造、全球研发测试、售后服务以及二手车全球贸易。
    的头像 发表于 05-20 15:24 334次阅读

    嵌入式中C语言结构基本实现

    C语言中的数组只能允许程序员定义存储相同类型数据。但是结构是C语言编程中允许您存储不同数据类型的数据结构
    的头像 发表于 05-11 08:49 1008次阅读
    嵌入式中C语言<b class='flag-5'>结构</b><b class='flag-5'>体</b>基本实现

    用FreeRTOS使用队列怎么发送一个结构呢?

    在函数osMessageGet 只能返回一个4个字节啊。在xQueueReceive它只传了一个uint32_tv啊,只有四个字节。 那就限制了最大的数据就是四个字节了,感觉应该不会是这样啊,那么我
    发表于 04-17 07:35

    揭秘USB报文的结构与运作机制

    握手包在一个字节的数据字段后由EOP定界如果一个数据包在解码为握手包的情况下,在一个字节后没有以EOP结束,它必须被视为无效并被接收器忽略
    发表于 04-10 10:56 1979次阅读
    揭秘USB报文的<b class='flag-5'>结构</b>与运作机制

    C语言结构史上最详细的讲解【软件干货】

    struct结构数据类型 前言 我们知道,在C语言中有一些基本的数据类型,如 char int float long double string(c99) 等等
    的头像 发表于 03-28 17:52 738次阅读

    磁栅尺中间没有数据的原因及解决方法

    磁栅尺中间没有数据的原因及解决方法!磁栅尺是一类主要用于测量长度和位置的精密测量专用工具。但是,很多时候可能会遇到磁栅尺中间没有数据的现象,这可能会导致测量结果不准确。当我们遇到磁栅尺中间没有数据
    的头像 发表于 03-06 14:37 954次阅读
    磁栅尺中间没<b class='flag-5'>有数据</b>的原因及解决方法

    arcgis值类型与字段类型不兼容

    ArcGIS是一个地理信息系统软件,可以用来处理、分析和可视化地理数据。在ArcGIS中,值类型和字段类型之间需要相互匹配,否则会导致不兼容的错误。 在ArcGIS中,值类型是指存储在数据字段
    的头像 发表于 02-25 11:14 1597次阅读

    can总线的数据帧中数据长度码和数据字节数的关系?

    can总线的数据帧中数据长度码和数据字节数的关系? CAN总线是一种常用于数据通信的协议,它使用数据帧来传输信息。在CAN
    的头像 发表于 01-31 11:31 2293次阅读

    求助,请问一个结构如何全部定义到 __attribute__ 区域?

    请问一个结构如何全部定义到 __attribute__ 区域? 例如我这里涉及到一些高速计算的缓存,计划将缓存数据存储到 __attribute__ 区域。 三个结构
    发表于 01-16 07:29

    经典 C 语言编程,结构和联合体如何共用?

    中可以 使用 sizeof 进行获取,默认为字节对齐的大小。 联合体 联合体的参数共享同一个内存地址,所占的内存大小完全是由联合体中参数类型决定字长,然后数据共享,内存共享等。 结构和联合体连用例子: 1、首先定义一个
    的头像 发表于 01-11 18:24 1329次阅读
    经典 C 语言编程,<b class='flag-5'>结构</b><b class='flag-5'>体</b>和联合体如何共用?

    结构与指针的关系

    在C语言中,结构(Struct)是一种用户自定义的数据类型,它允许您将不同类型的数据项组合在一起,以便形成一个更复杂的数据结构
    的头像 发表于 01-11 08:00 973次阅读
    <b class='flag-5'>结构</b><b class='flag-5'>体</b>与指针的关系