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

    文章

    7444

    浏览量

    163560
  • 内存
    +关注

    关注

    8

    文章

    2991

    浏览量

    73843
  • 结构体
    +关注

    关注

    1

    文章

    129

    浏览量

    10826

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

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

收藏 人收藏

    评论

    相关推荐

    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

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

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

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

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

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

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

    结构与指针的关系

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

    AD7701没有数据输入,DRDY无变化是为什么?

    配置上电后,AD7701的SDATA端口没有数据输入,有也只有一个脉冲时不时飘过,见下图,想问问是为什么?
    发表于 12-05 08:02

    给Oracle数据库添加表字段的代码

    TABLE语句来添加表字段。 首先,在开始操作之前,我们需要确保已经连接到了正确的Oracle数据库实例,并且有足够的权限来执行表结构的修改操作。 确定需要添加字段的表 首先,我们需
    的头像 发表于 11-21 11:38 794次阅读

    oracle数据库添加字段语句

    Oracle数据库添加字段语句是在已有表中添加新的列,以扩展表的结构和功能。添加字段语句的语法有多种,可以根据实际需求选择不同的语法。下面将详细介绍Oracle
    的头像 发表于 11-21 11:37 6518次阅读

    oracle修改表字段长度语句

    Oracle 修改表字段长度可以通过使用 ALTER TABLE 语句来实现。在对表进行修改之前,我们需要先了解一些基本的概念。 表字段长度是指在数据库表中用来存储数据的列的最大容量。
    的头像 发表于 11-21 11:34 1907次阅读

    oracle修改数据库表字段类型

    。 2.使用ALTER TABLE语句修改字段类型:在Oracle中,使用ALTER TABLE语句可以修改表的结构。通过ALTER TABLE语句,可以修改字段数据类型、大小和约束
    的头像 发表于 11-21 11:33 3167次阅读

    oracle更新clob字段sql语句

    在Oracle中,更新CLOB字段可以使用UPDATE语句。CLOB字段是用于存储大量文本数据数据类型,可以存储最多4GB的数据。下面是一
    的头像 发表于 11-21 11:29 3962次阅读

    oracle更新clob字段脚本写法

    在Oracle中更新CLOB字段需要使用PL/SQL块或SQL语句。下面是更新CLOB字段的不同方法和示例。 方法一:使用PL/SQL块更新CLOB字段 DECLARE clob_var CLOB
    的头像 发表于 11-21 11:28 2988次阅读

    clob字段怎么insert

    当涉及到插入含有CLOB字段数据时,需要采用特定的语法和方法来实现。本文将详细介绍如何插入CLOB字段数据,并提供了一个详细的示例。 一、了解CLOB
    的头像 发表于 11-21 11:27 3270次阅读

    clob 类型字段的内容类型

    数据、日志文件等。 CLOB字段的内容类型可以包括以下几种: 文本文档:CLOB字段可以存储大型的文本文档,如书籍、说明文档、报告等。这些文本文档通常包含不同的段落、标题、标签、索引等,可以通过CLOB
    的头像 发表于 11-21 11:26 1676次阅读

    数据库clob类型的字段怎么取

    数据库中的 CLOB(Character Large Object)类型字段存储的是大量的字符数据,如文本文件、XML 文件、图像等。要获取 CLOB 类型字段的值,可以使用以
    的头像 发表于 11-21 10:47 2448次阅读