C#与C++进行字段内存对齐

通过预留字段来补齐内存分配。在实际项目中采用这种方法较多,即保证了长度一致,也为以后的扩展提供了容错的可能性。

unsafe struct StructSequential{public fixed float x[8];public fixed float y[8];public fixed float z[8];public fixed float time[8];public fixed float radius[8];[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]public float[] reserved;}

或者

public unsafe struct RTCPointQuery8{public fixed float x[8];public fixed float y[8];public fixed float z[8];public fixed float time[8];public fixed float radius[8];}
Span<byte> stack = stackalloc byte[sizeof(RTCPointQuery8) + 32];
ref var test = ref StackAllocAligned<RTCPointQuery8>(stack, 32);static unsafe ref T StackAllocAligned<T>(Span<byte> stack, nuint alignment) where T : unmanaged{return ref Unsafe.AsRef<T>((void*)(((nint)Unsafe.AsPointer(ref MemoryMarshal.GetReference(stack))+ ((nint)alignment - 1)) & ~(nint)(alignment - 1)));}

C#内存对齐有三种方式,分别是:LayoutKind.SequentialLayoutKind.ExplicitLayoutKind.Auto

LayoutKind.Sequential

顺序对齐,这是默认的内存对齐方式。会按照定义的struct中最大成员的长度进行内存对齐,使用这种对齐方式容易造成内存空间浪费。这种方式常用于和非托管代码交互的情形,CLR对struct的Layout处理方法与C/C++中默认的处理方式相同,都是按照结构体中占用空间最大的成员进行内存对齐。

[StructLayout(LayoutKind.Sequential)]struct StructSequential{public int A;public char B;}public static void Start(){StructSequential structSequential = new StructSequential();Debug.WriteLine("A的长度为:{0}", Marshal.SizeOf(structSequential.A));Debug.WriteLine("B的长度为:{0}", Marshal.SizeOf(structSequential.B));Debug.WriteLine("structSequential的长度为:{0}", Marshal.SizeOf(structSequential));}
//A的长度为:4
//B的长度为:1
//structSequential的长度为:8

如果我们正在创建一个与非托管代码没有任何交互的struct类型,我们也希望改变C#编译器的这种默认规则,因此,除了Sequential外,还有Explicit和Auto。

除此之外,你还可以通过设置StructLayout.Pack的值来达到内存大小分配一致,但这种方法可能会因硬件性能约束或者其他的问题。

[StructLayout(LayoutKind.Sequential, Pack = 32)]unsafe struct StructSequential{public fixed float x[8];public fixed float y[8];public fixed float z[8];public fixed float time[8];public fixed float radius[8];}

LayoutKind.Explicit

精确对齐,CLR会按照程序的设置对内存进行精确对齐。传入LayoutKind.Explicit,可以使字段按照我们设定的FieldOffset设置字段排序方式,CLR不对结构体进行内存对齐;但是,这种方式也是有缺陷的,如果设置错误,后果将比较严重。

[StructLayout(LayoutKind.Explicit)]struct StructSequential{[FieldOffset(0)]public int A;[FieldOffset(0)]public char B;}public static void Start(){StructSequential structSequential = new StructSequential();Debug.WriteLine("A的长度为:{0}", Marshal.SizeOf(structSequential.A));Debug.WriteLine("B的长度为:{0}", Marshal.SizeOf(structSequential.B));Debug.WriteLine("structSequential的长度为:{0}", Marshal.SizeOf(structSequential));structSequential.A = 0;structSequential.B = '0';Debug.WriteLine("structSequential.A: {0}", structSequential.A);Debug.WriteLine("structSequential.B: {0}", structSequential.B);}
//A的长度为:4
//B的长度为:1
//structSequential的长度为:4
//structSequential.A: 48
//structSequential.B: 0

[FieldOffset(0)]表示内存不会有任何偏移,这种情形下,同一字节中存储了两条数据,当其中一条改变时,另一条也随之而改变。

LayoutKind.Auto

自动对齐。CLR会调整struct中成员的顺序来自动对齐,使实例仅可能占用更少的内存,同时会进行一定字节的内存对齐。 按照自己选择的最优方式对实例中的字段进行排列。

[StructLayout(LayoutKind.Auto)]struct StructSequential{public int A;public char B;}public static void Start(){StructSequential structSequential = new StructSequential();Debug.WriteLine("A的长度为:{0}", Marshal.SizeOf(structSequential.A));Debug.WriteLine("B的长度为:{0}", Marshal.SizeOf(structSequential.B));//Debug.WriteLine("structSequential的长度为:{0}", Marshal.SizeOf(structSequential));unsafe{Debug.WriteLine("structSequential的长度为:{0}", sizeof(StructSequential));}structSequential.A = 0;structSequential.B = 'a';Debug.WriteLine("structSequential.A: {0}", structSequential.A);Debug.WriteLine("structSequential.B: {0}", structSequential.B);} 

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

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

相关文章

在CentOS 7.9上搭建高性能的FastDFS+Nginx文件服务器集群并实现外部远程访问

文章目录 引言第一部分&#xff1a;FastDFS介绍与安装1.1 FastDFS简介1.2 FastDFS安装1.2.1 安装Tracker Server1.2.2 安装Storage Server 1.3 FastDFS配置1.3.1 配置Tracker Server1.3.2 配置Storage Server1.3.3 启动FastDFS服务 第二部分&#xff1a;Nginx配置2.1 Nginx安装…

Redis IO多路复用之select、poll和epoll

Redis 性能好除了它是基于内存的数据库外,还因为Redis 是基于IO多路复用机制。以下总结一下曾经遇到过的一个面试题:你了解IO多路复用机制吗?实现IO多路复用机制的方式有哪些?有什么区别? 是的,我了解Redis的IO多路复用机制。Redis使用IO多路复用来实现高效的异步非阻塞I…

Docker容器化部署若依微服务ruoyi-cloud项目

系统环境 接下来的内容以 Ubuntu 22.04.1 操作系统为例。 下载安装Docker Ubuntu hihi-IdeaCentre-GeekPro-15ICK:~$ sudo su [sudo] hi 的密码&#xff1a; roothi-IdeaCentre-GeekPro-15ICK:/home/hi# docker ps 找不到命令 “docker”&#xff0c;但可以通过以下软件包安…

Visual Studio 使用MFC 单文档工程绘制单一颜色直线和绘制渐变颜色的直线(实例分析)

Visual Studio 使用MFC 单文档工程从创建到实现绘制单一颜色直线和绘制渐变颜色的直线 本文主要从零开始创建一个MFC单文档工程然后逐步实现添加按键&#xff08;事件响应函数&#xff09;&#xff0c;最后实现单一颜色直线的绘制与渐变色直线的绘制o(&#xffe3;▽&#xffe…

【云原生】什么是 Kubernetes ?

什么是 Kubernetes &#xff1f; Kubernetes 是一个开源容器编排平台&#xff0c;管理着一系列的 主机 或者 服务器&#xff0c;它们被称作是 节点&#xff08;Node&#xff09;。 每一个节点运行了若干个相互独立的 Pod。 Pod 是 Kubernetes 中可以部署的 最小执行单元&#x…

之前运行的好好的pycharm文件运行不了

C:\Users\LENOVO\venv\Scripts\python.exe “D:\pyCharm\PyCharm 2018.3.2\helpers\pydev\pydevconsole.py” --modeclient --port55573 Traceback (most recent call last): File “D:\pyCharm\PyCharm 2018.3.2\helpers\pydev\pydevconsole.py”, line 33, in from _pydev_b…

2、Burp使用

文章目录 一、为Firefox浏览器安装数字证书二、利用Intruder模块进行暴力破解 一、为Firefox浏览器安装数字证书 &#xff08;1&#xff09;利用Firefox浏览器访问http://burp或127.0.0.1:<监听端口>&#xff0c;点击页面右上侧的“CA Certificate”处下载CA证书&#xf…

机器学习---贝叶斯网络与朴素贝叶斯

1. 贝叶斯法则 如何判定一个人是好人还是坏人&#xff1f; 当你无法准确的熟悉一个事物的本质时&#xff0c;你可以依靠与事物特定本质相关的事件出现的次数来判断 其本质属性的概率。如果你看到一个人总是做一些好事&#xff0c;那这个人就越可能是一个好人。 数学语言表达…

float和double(浮点型数据)在内存中的储存方法

作者&#xff1a;元清加油 主页&#xff1a;主页 编译环境&#xff1a;visual studio 2022 (x86) 相信大家都知道数据在内存中是以二进制储存的 整数的储存方法是首位是符号位&#xff0c;后面便是数值位 那么浮点数在内存中是怎么储存的呢&#xff1f;我们先来看一个例子&am…

数据结构与算法之二叉树: LeetCode 100. 相同的树 (Typescript版)

相同的树 https://leetcode.cn/problems/same-tree/ 描述 给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 示例 1 1 1/ \ / …

Android WiFi的断开分析

1.wifi断开大体流程&#xff1a; 1.wifi断开 wlan-driver最先知道。 2.wlan-driver在与路由器连接的时候(未断开时), 会有周期性的beacon帧来维持连接&#xff0c;AP端一旦遇到突发事情&#xff0c;会立刻通过802.11协议的 deauth 帧/ reject 帧等 通知到 driver。 3. wlan-…

【Java程序员面试专栏 专业技能篇 】Java SE核心面试指引(四):Java新特性

关于Java SE部分的核心知识进行一网打尽,包括四部分:基础知识考察、面向对象思想、核心机制策略、Java新特性,通过一篇文章串联面试重点,并且帮助加强日常基础知识的理解,全局思维导图如下所示 本篇Blog为第四部分:Java新特性,子节点表示追问或同级提问 Java8新特性…

【部署运维】docker:入门到进阶

0 前言 部署运维博客系列一共有三篇&#xff1a; 拥抱开源&#xff0c;将工作中的经验分享出来&#xff0c;尽量避免新手踩坑。 【部署运维】docker&#xff1a;入门到进阶 【部署运维】kubernetes&#xff1a;容器集群管理掌握这些就够了 【部署运维】pythonredisceleryd…

快速、精确仿真高频电磁场的工具CST Studio Suite 2024版本下载与安装配置

目录 前言一、CST 2024 安装二、使用配置总结 前言 CST Studio Suite是一个集成的仿真工具套件&#xff0c;用于模拟和优化电子系统的性能。它包括多个工具和模块&#xff0c;如电磁仿真、结构仿真、热仿真、电路分析等&#xff0c;以支持从概念设计到生产部署的整个开发周期。…

【Python】多年数据分成不同sheet

需求&#xff1a; excel文件中包含多年数据&#xff0c;其中一列列名为“年”&#xff0c;要保存一个新excel&#xff0c;将年数值不同的行保存在不同的sheet文件中&#xff0c;每个sheet文件第一行仍为原数据第一行&#xff0c;并且每个sheet名为对应的年的值。 拆分年份数据…

Vue19 列表过滤

直接上代码 以下代码使用了两种实现方式&#xff0c;监视属性和计算属性 当能用计算属性实现时&#xff0c;推荐使用计算属性 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>列表过滤</title><script type&q…

Java中的jvm——面试题+答案(Java虚拟机更深层次的概念和原理,包括字节码、代理、内存管理、并发等)——第17期

什么是即时编译&#xff08;JIT Compilation&#xff09;&#xff1f; 答案&#xff1a; 即时编译是一种在运行时将字节码转换为本地机器代码的技术&#xff0c;以提高程序的执行速度。JVM中的JIT编译器负责执行这个过程。 什么是Java字节码&#xff1f;为什么Java使用字节码…

阿里元境亮相第八届世界物联网大会,分享元计算对数字文旅的创新赋能

2023&#xff08;第八届&#xff09;世界物联网大会于11月20日在中国北京隆重开幕。联合国秘书长安东尼奥古特雷斯在开幕式发表书面致辞时特别提到&#xff1a;“在一个相互连接的世界&#xff0c;你们的主题‘新物联、新经济、新时代’是数字技术影响力的见证”。 11月21日上午…

auth模块

一. auth模块前戏 # 引入:其实我们在创建好一个django项目之后直接执行数据库迁移命令会自动生成很多表 例如:django_sessionauth_user我们知道django在启动之后就可以直接访问admin路由&#xff0c;需要输入用户名和密码&#xff0c;数据参考的就是auth_user表,并且还必须是管…

使用Java编写串口程序

引言 串口是计算机与外部设备进行通信的一种常见方式。在很多领域中&#xff0c;例如物联网、嵌入式系统和工业自动化等&#xff0c;都需要通过串口与设备进行数据交互。Java作为一种跨平台的编程语言&#xff0c;在串口通信方面也提供了相应的API和库&#xff0c;方便开发者进…