CAP结构体之字节对齐

news2025/1/11 13:01:06
  • 🍅 我是蚂蚁小兵,专注于车载诊断领域,尤其擅长于对CANoe工具的使用
  • 🍅 寻找组织 ,答疑解惑,摸鱼聊天,博客源码,点击加入👉【相亲相爱一家人】
  • 🍅 玩转CANoe,博客目录大全,点击跳转👉

请添加图片描述

目录

      • CAPL为什么也要理解字节对齐呢?
      • CAPL 字节对齐脚本实例
  • 🌎总结


CAPL为什么也要理解字节对齐呢?

一般情况下,我们在定义/使用结构体的情况下,不需要考虑字节对齐的问题,因为CAPL运行在WIndows系统上,我们也不差那点内存消耗,但是如果你想更进一步的运用结构体,比如下面的CAPL函数结构体和数组想换转换时就要考虑到结构体字节对齐的问题了,不然有可能得不到期望的结果

在这里插入图片描述在这里插入图片描述

CAPL 字节对齐脚本实例

计算机中内存大小的基本单位是字节(byte),理论上来讲,可以从任意地址访问某种基本数据类型,但是实际上,为了内存读写效率,计算机并非逐字节大小读写内存,而是以2,4,或8的倍数的字节块来读写内存,如此一来就会对基本数据类型的合法地址作出一些限制,即它的地址必须是2,4或8的倍数。那么就要求各种数据类型按照一定的规则在空间上排列,这就是对齐。

CAPL 基于C语言,但是CAPL有自己的字节对齐规则,且CAPL封装了自己的函数来读取字节对齐和设置字节对齐,下图是结构体字节对齐的相关函数
在这里插入图片描述
先看一个简单的示例,结构元元素是相同的元素,结构体大小就是所有元素的字节大小之和。

on key 'b'
{
 struct Point
  {   
    byte x;         // offset 0, size 1
    byte y;         // alignment 1, offset 1, size 1, padding before: 0
  };               // size 2, alignment (of the struct) 1
  

  write("结构体占内存字节数:%d",__size_of(struct Point));
  write("结构体的字节对齐:%d",__alignment_of(struct Point));
  write("结构体的元素x内存地址偏移量:%d",__offset_of(struct Point,x));  
  write("结构体的元素y内存地址偏移量:%d",__offset_of(struct Point,y));  
}

输出结果
Program / Model 结构体占内存字节数:2
Program / Model 结构体的字节对齐:1
Program / Model 结构体的元素x内存地址偏移量:0
Program / Model 结构体的元素y内存地址偏移量:1

  • 结构体元素不是相同类型时:
  • 字节对齐大小是结构体中元素最大的那个元素,如果最大成员的类型是qword(8字节),则该结构体的字节对齐大小就是8字节
  • 如果结构体的后一个成员比前一个成员大,则后一个成员的内存地址偏移量 = 前一个内存地址偏移量 + 后一个成员的字节大小 。比如qword前面是byte ,则 qword的内存偏移量是就是(0+8)
  • 如果结构体的后一个成员比前一个小,则后一个成员的内存地址偏移量 = 前一个内存地址偏移量 + 前一个成员字节大小 。 比如byte z比 qword y 小,则 byte z的偏移量(16)= 8+8
  • 结构体占内存大小(20) = 最后一个元素的偏移量(18) + 它的大小(2)
on key 'b'
{
struct LongPoint 
{  
  byte x;              // offset 0, size 1
  qword y;             // alignment 8, offset 8, size 8, padding before: 7
  byte z;             // alignment 1, offset  16, size 1, padding before: 0
  int k;             // alignment 2, offset  18, size 2, padding before: 1
};                   // size 20, alignment (of the struct) 8
  

  write("结构体占内存字节数:%d",__size_of(struct LongPoint));
  write("结构体的字节对齐:%d",__alignment_of(struct LongPoint));  
  write("结构体的元素x内存地址偏移量:%d",__offset_of(struct LongPoint,x)); 
  write("结构体的元素y内存地址偏移量:%d",__offset_of(struct LongPoint,y)); 
  write("结构体的元素z内存地址偏移量:%d",__offset_of(struct LongPoint,z)); 
  write("结构体的元素k内存地址偏移量:%d",__offset_of(struct LongPoint,k)); 
}

输出结果
Program / Model 结构体占内存字节数:20
Program / Model 结构体的字节对齐:8
Program / Model 结构体的元素x内存地址偏移量:0
Program / Model 结构体的元素y内存地址偏移量:8
Program / Model 结构体的元素y内存地址偏移量:16
Program / Model 结构体的元素y内存地址偏移量:18

CAPL字节对齐的原则:字节对齐数字只有1, 2, 4, 8可以用,如果没有指定,则默认字节对齐大小为结构体元素中最大元素的字节大小。可以通过_align() 函数来指定对齐大小
下面代码通过设置_align(1) ,_align(2) ,_align(4) 来对比下结果。

on key 'b'
{
  
{
   struct LongPoint 
  {  
    byte x;              
    qword y;             
    byte z;             
    int k;            
  };                   
  
  write("*********************默认对齐大小********************************");
  write("结构体占内存字节数:%d",__size_of(struct LongPoint));
  write("结构体的字节对齐:%d",__alignment_of(struct LongPoint));  
  write("结构体的元素x内存地址偏移量:%d",__offset_of(struct LongPoint,x)); 
  write("结构体的元素y内存地址偏移量:%d",__offset_of(struct LongPoint,y)); 
  write("结构体的元素z内存地址偏移量:%d",__offset_of(struct LongPoint,z)); 
  write("结构体的元素k内存地址偏移量:%d",__offset_of(struct LongPoint,k)); 
}
  
{
  _align(1) struct LongPoint 
  {  
    byte x;              
    qword y;             
    byte z;             
    int k;            
  };                   
  
  write("*********************_align(1) ********************************");
  write("结构体占内存字节数:%d",__size_of(struct LongPoint));
  write("结构体的字节对齐:%d",__alignment_of(struct LongPoint));  
  write("结构体的元素x内存地址偏移量:%d",__offset_of(struct LongPoint,x)); 
  write("结构体的元素y内存地址偏移量:%d",__offset_of(struct LongPoint,y)); 
  write("结构体的元素z内存地址偏移量:%d",__offset_of(struct LongPoint,z)); 
  write("结构体的元素k内存地址偏移量:%d",__offset_of(struct LongPoint,k)); 
}
{
  _align(2) struct LongPoint 
  {  
    byte x;              
    qword y;             
    byte z;             
    int k;            
  };                   
  
  write("*********************_align(2) ********************************");
  write("结构体占内存字节数:%d",__size_of(struct LongPoint));
  write("结构体的字节对齐:%d",__alignment_of(struct LongPoint));  
  write("结构体的元素x内存地址偏移量:%d",__offset_of(struct LongPoint,x)); 
  write("结构体的元素y内存地址偏移量:%d",__offset_of(struct LongPoint,y)); 
  write("结构体的元素z内存地址偏移量:%d",__offset_of(struct LongPoint,z)); 
  write("结构体的元素k内存地址偏移量:%d",__offset_of(struct LongPoint,k)); 
}
{
  _align(4) struct LongPoint 
  {  
    byte x;              
    qword y;             
    byte z;             
    int k;            
  };                   
  
  write("*********************_align(4) ********************************");
  write("结构体占内存字节数:%d",__size_of(struct LongPoint));
  write("结构体的字节对齐:%d",__alignment_of(struct LongPoint));  
  write("结构体的元素x内存地址偏移量:%d",__offset_of(struct LongPoint,x)); 
  write("结构体的元素y内存地址偏移量:%d",__offset_of(struct LongPoint,y)); 
  write("结构体的元素z内存地址偏移量:%d",__offset_of(struct LongPoint,z)); 
  write("结构体的元素k内存地址偏移量:%d",__offset_of(struct LongPoint,k)); 
}

}

输出结果:
Program / Model 默认对齐大小***********
Program / Model 结构体占内存字节数:20
Program / Model 结构体的字节对齐:8
Program / Model 结构体的元素x内存地址偏移量:0
Program / Model 结构体的元素y内存地址偏移量:8
Program / Model 结构体的元素z内存地址偏移量:16
Program / Model 结构体的元素k内存地址偏移量:18
Program / Model *********************_align(1) ********************************
Program / Model 结构体占内存字节数:12
Program / Model 结构体的字节对齐:1
Program / Model 结构体的元素x内存地址偏移量:0
Program / Model 结构体的元素y内存地址偏移量:1
Program / Model 结构体的元素z内存地址偏移量:9
Program / Model 结构体的元素k内存地址偏移量:10
Program / Model *********************_align(2) ********************************
Program / Model 结构体占内存字节数:14
Program / Model 结构体的字节对齐:2
Program / Model 结构体的元素x内存地址偏移量:0
Program / Model 结构体的元素y内存地址偏移量:2
Program / Model 结构体的元素z内存地址偏移量:10
Program / Model 结构体的元素k内存地址偏移量:12
Program / Model *********************_align(4) ********************************
Program / Model 结构体占内存字节数:16
Program / Model 结构体的字节对齐:4
Program / Model 结构体的元素x内存地址偏移量:0
Program / Model 结构体的元素y内存地址偏移量:4
Program / Model 结构体的元素z内存地址偏移量:12
Program / Model 结构体的元素k内存地址偏移量:14

在这里插入图片描述

🌎总结

23

7

  • 🚩要有最朴素的生活,最遥远的梦想,即使明天天寒地冻,路遥马亡!

  • 🚩如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。
    18

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

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

相关文章

No10.精选前端面试题,享受每天的挑战和学习

文章目录 Linux 中五种 IO 模型四次挥手之后为什么还要等待 2mslcookie 和 session 的区别是什么tcp 怎么保证可靠性css实现图片自适应宽高的几种方法 Linux 中五种 IO 模型 在 Linux 中,常见的五种 I/O(Input/Output)模型包括: …

机器学习19:多类别神经网络-Multi-Class Neural Networks

在【机器学习12:分类 Classification】一文中,笔者介绍了二元分类模型,它可以在两个可能的选择之一之间进行选择,例如: 电子邮件是垃圾邮件还是非垃圾邮件。肿瘤是恶性的或良性的。 在本文中,我们将研究多类…

将ChatGPT变成Midjourney提示生成器

已经有人总结过可以让ChatGPT作为Midjourney图像生成的模板。在本文中,我们将展示如何根据个人用例创建这些提示,这可以让ChatGPT生成的提示可控性更高。 选择提示模板 Midjourney的模板结构性很强,所以我们这里使用一下的结构: …

rsync远程同步(可爱可抵漫长岁月)

文章目录 一、简介二、部署rsync主客服务器1.关闭防火墙(真的老生常谈了 一生之敌!)2.建立/etc/rsyncd.conf 配置文件3.客户端配置4.发起端配置 rsyncinotify 三、拓展使用rsync来实现快速删除大量文件。 一、简介 什么是rsync? …

【Linux】Linux项目自动化构建工具-make/makefile

Linux项目自动化构建工具-make/makefile 什么是make/makefile?make/makefile的使用依赖关系依赖方法makefile是如何工作的?为什么要使用makefile呢?makefile是怎么做到的呢?make和make clean.PHONY:伪目标 特殊符号&am…

Vue 之 mixins 和 provide/inject

一、mixins 1、简介 ​ mixins 又称 混入,是指将一些可复用的代码(JS、生命周期钩子函数等等)抽离出来,定义成mixins模块,然后混入到多个组件中,从而实现组件间的逻辑代码共享,减少重复代码。…

Nginx正向代理、反向代理,动静分离

目录 正向代理 反向代理 动静分离 正向代理 正向代理最大的特点是客户端非常明确要访问的服务器地址;服务器只清楚请求来自哪个代理服务器,而不清楚来自哪个具体的客户端;正向代理模式屏蔽或者隐藏了真实客户端信息。 反向代理 客户端给服…

C#(四十六)之基于流的文件操作(FileStream)

FileStream类属性和方法 属性 CanRead 指示当前文件流是否支持读取 CanWrite 指示当前文件流是否支持写入 CanSeek 指示当前文件流是否支持查找 IsAsync FileStream是同步打开还是异步打开 Length 流的长度(字节数) CanTimeOut 当前文件流是否可以…

【C++进阶】哈希表

文章目录 前言哈希概念哈希冲突哈希函数哈希冲突解决一.闭散列解决哈希冲突1. 线性探测2.二次探测 二、闭散列的实现1.准备2.闭散列插入3.闭散列查找4.闭散列删除 三、闭散列完整源码四、开散列解决哈希冲突1.开散列概念2.哈希桶的结构3.哈希桶的插入4.哈希桶的查找5.哈希桶的删…

学习多线程

1、学习线程池 1.1jdk中的线程池 推荐使用ThreadPoolExecutor 1.1.1先了解参数的意义 首先看下ThreadPoolExecutor的构造函数 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueu…

对话e签宝,解读 SaaS圈“头部玩家”的增长故事

可以肯定的是&#xff0c;未来3年&#xff0c;整个中国SaaS市场会逐步确认船票分配。穿越周期&#xff0c;告别不确定的三年&#xff0c;给幸存下来的企业上了淋漓生动的一课。在新的起点上&#xff0c;SaaS也需要一种新的打开方式。谁扎得牢、想得透、做的好、跑得快&#xff…

Docker数据卷和数据卷容器应用

学习目的 掌握Docker数据卷和数据卷容器使用方法。 学习准备 要求实验主机能够连接外网&#xff0c;已经正确安装Docker&#xff0c;并关闭防火墙和selinux。 学习步骤 步骤1&#xff1a;创建数据卷 &#xff08;1&#xff09;创建容器&#xff0c;为容器添加一个数据卷&…

基于树莓派4B与STM32的智能门禁系统项目(代码开源)

前言&#xff1a;本文为手把手教学嵌入式经典项目——智能门禁项目&#xff0c;本次项目采用 树莓派4B 与 STM32F103C8T6 进行联合开发。项目充分发挥各自 CPU 的优势与长处&#xff0c;将人脸识别的大计算量任务给树莓派4B&#xff0c;将门禁系统的控制部分交给 STM32 进行处理…

外包干了2个月,技术退步明显...

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

举个栗子!Quick BI 技巧(1):创建趋势折线图

自 2016 年以来&#xff0c;优阅达《举个栗子》内容专栏已陪伴众多企业用户高效工作&#xff0c;解决真实业务场景中的用数问题。 2023 年&#xff0c;全新系列《举个栗子&#xff01;Quick BI 技巧》出炉啦~ 优阅达期待能够持续分享经验&#xff0c;帮助用户发现更多 Quick …

剑指 Offer. 二叉树中和为某一值的路径

给你二叉树的根节点 root 和一个整数目标和 targetSum &#xff0c;找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum 22 输出&…

ATA3000系列功率放大器——水声信号中的典型应用

ATA3000系列功率放大器——水声信号中的典型应用 水声领域介绍&#xff1a; 主动声纳是通过声纳本身发射声波&#xff0c;根据声信号反射回波来发现目标&#xff0c;并测定目标的位置和运动参数。水声信号发射机在主动声纳设备中是非常重要的组成部分&#xff0c;其产生特定形式…

YoloV5/YoloV7改进---注意力机制:引入瓶颈注意力模块BAM,对标CBAM

目录 1.BAM介绍 2.BAM引入到yolov5 2.1 加入common.py中&#xff1a; 2.2 加入yolo.py中&#xff1a; 2.3 yolov5s_BAM.yaml 1.BAM介绍 论文&#xff1a;https://arxiv.org/pdf/1807.06514.pdf 摘要&#xff1a;提出了一种简单有效的注意力模块&#xff0c;称为瓶颈注意力模块…

【数据仓库】Apache Doris介绍

Apache Doris介绍 Apache Doris应用场景 Apache Doris核心特性 Apache Doris架构 Doris数据模型三种 Aggregate模型介绍 Uniq模型介绍 在某些多维分析场景下,用户更关注的是如何保证Key的唯一性Key 唯一性约束。因此&#xff0c;我们引入了 Unig 的数据模型。该模型本质上是聚…

微信如何创建自己的小程序?

微信如何创建自己的小程序&#xff1f;微信小程序成为了很多商家、企业甚至是个人在互联网中的营销工具&#xff0c;微信小程序基本上可以说是属于必备工具。那么微信如何创建自己的小程序呢&#xff1f;下面一起来给大家说说。 一、注册小程序账号 微信如何创建自己的小程序…