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

    文章

    7141

    浏览量

    161973
  • 内存
    +关注

    关注

    8

    文章

    2763

    浏览量

    72751
  • 结构体
    +关注

    关注

    1

    文章

    125

    浏览量

    10749

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

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

收藏 人收藏

    评论

    相关推荐

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

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

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

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

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

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

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

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

    oracle数据库添加字段语句

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

    oracle修改数据库表字段类型

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

    oracle更新clob字段sql语句

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

    clob字段怎么insert

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

    clob 类型字段的内容类型

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

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

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

    oracle怎么把clob字段转换为字符串

    将CLOB字段转换为字符串,可以使用PL/SQL中的DBMS_LOB包提供的函数来实现。 在Oracle数据库中,CLOB(Character Large Object)是用于存储大量字符数据
    的头像 发表于 11-21 10:32 3896次阅读

    如何在DEBUG的时候实时观察SYSTICK结构数据

    在DEBUG这个delay函数的时候,想要观察SysTick指向的结构数据变化,但是添加了SysTick到Watch1中,观察不了。 目前是定义了一个u32 temp采用了将SysTick中
    发表于 10-18 06:29

    结构在FLASH的存放中,数据地址是连续的吗?

    结构在FLASH的存放中,数据地址是连续的吗
    发表于 10-12 06:06

    CAN总线测试包括几个层面 can总线的诊断步骤

    CAN总线使用帧的方式进行数据传输。每个数据帧包含一个标识符(ID)字段、控制字段数据字段和校验字段
    发表于 08-11 14:12 3857次阅读

    Dataedo数据字典:为您的数据增添意义

      为您的数据增添意义 使用业务友好的别名解密表名和列名 通过描述提供数据资产的含义和目的 使用最多100个自定义字段来描述数据 捕获和记录关系 表和
    的头像 发表于 06-19 09:52 477次阅读
    Dataedo<b class='flag-5'>数据字</b>典:为您的<b class='flag-5'>数据</b>增添意义