C语言结构体4字节对齐对效率的影响

news2024/9/9 8:20:07

在定义通信协议时,结构体一般是按1字节对齐的,这样可以防止不同平台下默认字节对齐不一致的问题。那常说的非4字节对齐影响效率到底体现在哪呢?
来看下面两个结构:

#prama pack(1)
   typedef struct TNoAlign {
        char ch1;
        char ch2;
        char ch3;
        short sh4;
    }TNoAlign;

    typedef struct TAlign {
        short sh4;
        char ch1;
        char ch2;
        char ch3;
    }TAlign;

#pragma pack()

两个结构体都按1字节对齐,加上了#pragma标签。
先打印一下两个结构体各个成员在内存中的地址:

	TNoAlign tNoAl;
    TAlign tAl;

    tNoAl.ch1 = 1;
    tNoAl.ch2 = 2;
    tNoAl.ch3 = 3;
    tNoAl.sh4 = 4;

    tAl.ch1 = 1;
    tAl.ch2 = 2;
    tAl.ch3 = 3;
    tAl.sh4 = 4;


    printf("%d, %d, %d, %d\n", (int)((int*)&tNoAl.ch1), (int)((int*)&tNoAl.ch2), (int)((int*)&tNoAl.ch3), (int)((int*)&tNoAl.sh4));
    printf("%d, %d, %d, %d\n", (int)((int*)&tAl.sh4), (int)((int*)&tAl.ch1), (int)((int*)&tAl.ch2), (int)((int*)&tAl.ch3));

结果如下:

7338908, 7338909, 7338910, 7338911
7338892, 7338894, 7338895, 7338896

我们展开到结构体上:

typedef struct TNoAlign {
        char ch1; //7338908
        char ch2; //7338909
        char ch3; //7338910
        short sh4; //7338911
    }TNoAlign;

    typedef struct TAlign {
        short sh4; //7338892
        char ch1; //7338894
        char ch2; //7338895
        char ch3; //7338896
    }TAlign;

当对结构体的某个成员进行赋值或取值操作时,实际上是CPU找到结构体成员对应的地址的数据进行操作,这里有个寻址的过程,32位CPU大多有下面的规则:

CPU只能寻址4或8整除的地址,如果要寻址其他地址,比如0x00000003,则会寻址到0x00000000上取出4字节再找到第3位置上的数据,如果此时的数据比较长,比如有4个数据,那么第一次寻址只能拿到0x00000000取出4字节的最后一个,然后再寻址0x00000004,拿出剩余的3字节,这样就寻址了两次,花费的时间更多了

在本例中,先看TNoAlign ,当取(或者赋值)ch1时,没问题,ch2和ch3都可以取ch1的地址7338908拿到。当取sh4时,问题就来了,只能先取7338908拿到第一个字节,再取7338910拿到第二个字节。
TAlign 就没这个问题了,ch3可以直接拿到!但TAlign如果定义一个结构体数组时,依然有问题,因为整个结构体占5个字节,后面的取值或者赋值成员时,就会面临不对齐的问题,此时TAlign应该改为如下形式:

typedef struct TAlign {
        short sh4;  
        char ch1;  
        char ch2;  
        char ch3;  
        char chReserve[3]; //保留
    }TAlign;

这样就凑够了8字节,放到数组中也没有问题了。

看一下不是很准确的测试:

int iCount = 1000000000;
    auto ts = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
    for (int i = 0; i < iCount; i++) {
        tNoAl.ch1 = i;
        tNoAl.ch2 = i;
        tNoAl.ch3 = i;
        tNoAl.sh4 = i;
    }
    auto te = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
    std::cout << "time:" << te - ts << std::endl;

    auto ts2 = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
    for (int i = 0; i < iCount; i++) {
        tAl.ch1 = 1;
        tAl.ch2 = 2;
        tAl.ch3 = 3;
        tAl.sh4 = 4;
    }
    auto te2 = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
    std::cout << "time:" << te2 - ts2 << std::endl;

分别进行简单的赋值操作,最终的时间耗费如下:

time:4385
time:1722

可以看到,第二个效率高了两倍还多!

总结:

1. 结构体内部,int和short等谁宽谁往前放,char不要在中间定义,比如:

typedef struct TAlign {
        int
        short ;  
        short;  
        char ;  
        char ;  

    }TAlign;

如果实在想在中间定义char,则在中间添加保留位:

typedef struct TAlign {
        int
        char
        char reserve[3];
        short ;   
        char ;  
        char ;  

    }TAlign;

2. 结构体如果要往数组或者缓冲区里放,那么必须整体字节数是4的整数倍(上面已经说了)

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

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

相关文章

速看!2024年5月软考通过率解析

根据湖南省工业和信息化厅最新发布的《2024年上半年软考湖南考区工作总结报告》及《考试安全顺利完成的通报》&#xff0c;我们了解到湖南地区在2024年上半年度的软件与信息技术专业人才考试&#xff08;简称“软考”&#xff09;中&#xff0c;报名人数达到了13,762人&#xf…

无人机1公里WiFi图传遥控模组,飞睿智能无延迟传输方案,高效稳定告别卡顿

在信息众多的时代&#xff0c;我们享受着科技带来的便利&#xff0c;同时也期待着更多前沿技术的出现。今天&#xff0c;就让我们一起走进一个充满神秘与可能性的领域——飞睿智能1公里WiFi图传遥控模组。这个看似简单的设备&#xff0c;却蕴含着巨大的能量&#xff0c;它正在悄…

深度学习-感知机

目录 感知机训练感知机感知机模型感知机学习算法 收敛定理XOR问题总结 多层感知机学习XOR隐藏层单隐藏层---单分类激活函数Sigmoid激活函数Tanh 激活函数ReLU 激活函数 多类分类---单隐藏层多类分类---多隐藏层总结 多层感知机从零开始多层感知机的简洁实现总结 感知机 给定输…

智慧通信|IEEE Trans. Commun. 论文解读:延迟敏感的能量收集无线传感器的最佳调度、结构特性和近似分析

原文信息 Sharma, Nikhilesh, Nicholas Mastronarde, and Jacob Chakareski. “Delay-sensitive energy-harvesting wireless sensors: Optimal scheduling, structural properties, and approximation analysis.” IEEE Transactions on Communications 68.4 (2019): 2509-25…

OZON如何查询销量,OZON查销量哪里可以看

在竞争激烈的电商市场中&#xff0c;了解商品销量是每位卖家优化销售策略、提升竞争力的关键。作为俄罗斯领先的跨境电商平台&#xff0c;Ozon为卖家提供了丰富的数据支持&#xff0c;帮助卖家更好地掌握市场动态。然而&#xff0c;对于新手卖家来说&#xff0c;如何在Ozon上查…

1、爬⾍概述

1. 什么是爬虫&#xff1f; 爬虫&#xff08;Web Crawler&#xff09;是一种通过编写程序自动访问并提取互联网上数据的技术。爬虫可以帮助我们在浏览网页时自动收集和保存一些有用的数据&#xff0c;例如图片、视频和文本信息。简单来说&#xff0c;爬虫就是自动化的浏览器。…

InsightFace 人脸识别算法实现过程解析

最近研究了一下人脸识别算法&#xff0c;初步实现了基础的人脸识别。 源码github下载地址&#xff1a;insightface 第一步 解压源码配置环境 1、使用conda虚拟环境创建insightface环境 conda create -n insightface python3.8创建环境完成后&#xff0c;激活环境 conda ac…

手把手教你如何在宝塔上添加可道云登录页面的ICP备案信息,别跟权威开玩笑。

如何在宝塔上添加可道云登录页面的ICP备案信息 事情的原由来我们开始吧首先登录你的宝塔页面双击打开index.php文件保存退出即可 感谢大佬&#xff0c;希望对被查到的朋友有所帮助&#xff01; 事情的原由 今天突然收到腾讯云发来的一封Email&#xff0c;说我需要整改我的网站…

如何在职场上生存,送你3条秘技

洞悉本质才能方向明确&#xff0c;掌握方法才能事半功倍。 下面这3条职场生存的秘技&#xff0c;都是“过来人”的经验之谈&#xff0c;不管在哪里工作&#xff0c;都能管中窥豹、可见一斑&#xff0c;实在是值得深刻领悟。 01 你和领导的本质关系是工作关系 你有价值&#xff…

嵌入式开发服务器与客户端交互 日志2024/7/31

嵌入式开发服务器与客户端交互 客户端 网页 操作 请求相关代码: 这里为了适配 低版本浏览器 用的不是fetch 当然用fetch更好 var curUlr window.location.href; //获取当前网页地址var newURL curUlr.lastIndexOf("/");//截取到最后一个斜杠索引var pathUrl…

Python:如何实现对表格的自动化

前情提要&#xff1a;需要有openpyxl哦 如果没有请参考上一篇文章 http://t.csdnimg.cn/fjbLJ 先介绍一下对表格的基本操作 首先创立一个 transactions.xlsx 基本操作&#xff1a;获取表格&#xff0c;获取值 import openpyxl as xl # 这个as 单纯简化 相当于别名 wbxl.load_…

02 I/O多路复用---进程的聊天

服务器同时和很多客户端连在一起 管道的read&#xff0c;总是能读出来

mysql逻辑架构与sql执行过程

目录 1.背景 2.mysql逻辑架构图 3.逻辑架构解读 第一层:连接层 第二层:服务层 1.Management Serveices & Utilities 2.SQL Interface:SQL接口 3.Parser:解析器 4.Optimizer:查询优化器 5.Caches 和 Buffers:查询缓存组件 第三层:存储引擎层 第四层:数据存储层 …

【数据结构初阶】千字文章带你征服 “ 双向链表 ”(附源码)

hi&#xff0c;bro&#xff01;又见面啦 目录 前言&#xff1a; 一、链表的分类 二、双向链表 1、 概念与结构 2、 双向链表的实现 2.1 定义双向链表的结构 2.2 初始化 2.3 尾插 2.4 头插 2.5 打印 2.6 尾删 2.7 头删 2.8 查找 2.9 在pos结点之后插入…

实验室责任人员管理保障实训系统安全

在智慧校园的实训管理生态中&#xff0c;实验室责任人员的角色犹如精密机器中的关键齿轮&#xff0c;他们不仅是实验室安全与高效运转的守护者&#xff0c;更是实训教学质量的直接塑造者。这一角色的重要性&#xff0c;在智慧校园的数字化转型中得到了前所未有的凸显&#xff0…

过期知识:thinkphp5 使用migrate给现有的数据表新增表字段

个人开发网站记录, 这个文章主要是个以后健忘的我看的. 我在搞我的画笔审核 , 发现数据表的画笔数据在审核驳回的时候还是软删除好一些, 免得用户找不到之前上传的画笔数据, 后期也可以考虑重新显示给用户,让用户可以修改画笔信息重新提交审核. 这个时候想起了…

ViewModel相关

郭霖公众号 原作者原文 前言 ViewModel不仅是Activity和Fragment的数据集中管理和通讯&#xff0c;也是促进了MVVM和MVI架构规范&#xff0c;此文为深入理解ViewModel 概念 ViewModel是复制准备和管理Activity和Fragment数据的类&#xff0c;他还处理Activity或Fragment与应…

探索天穹数仓自治能力的新实践

探索天穹数仓自治能力的新实践 随着业务和技术的发展&#xff0c;传统数仓模式向数智数仓模式演进&#xff0c;数据治理面临诸多挑战。自治平台采用双引擎策略&#xff0c;注重感知能力、观测能力、诊断能力和优化能力的建设&#xff0c;实现了对数据的精细化管理。例如&#x…

鸿蒙应用框架开发【基于原生能力的无障碍模式】

基于原生能力的无障碍模式 介绍 本示例基于系统提供的无障碍阅读能力&#xff0c;实现了无障碍扩展服务集成、原生组件屏幕朗读以及多个控件组合标注。 效果图预览 原生组件屏幕朗读&#xff1a; 创建说明&#xff1a; 在已创建工程的ets文件夹下创建accessibility文件夹&…

SCIEI双检CCF期刊,硕博毕业生的福音,投稿欲从速!

SCI&EI双检CCF期刊&#xff0c;目前已稳定检索46年&#xff0c;CCF-C类&#xff0c;且发文量稳定&#xff0c;国人友好&#xff0c;发过的人都说审稿极速。 期刊详情 【期刊简介】IF&#xff1a;4.0-5.0 JCR1区中科院3区 【出版社】Elsevier出版社 【检索情况】SCI&a…