`
dazhilao
  • 浏览: 247216 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

C#结构体内存布局介绍

    博客分类:
  • C#
阅读更多
本来打算写一篇文章,详细地讨论一下结构的内存布局,但是想了下,跟路西菲尔的这篇文章也差不多,所以这里只做一下补充:

一、对齐长度

如果没有显式的指定对齐长度,将以结构中占用空间最大的成员的长度作为对齐长度;如果要显式指定对齐长度,需设置StructLayoutAttribute.Pack,如:

 
   [StructLayout(LayoutKind.Sequential,Pack=4)]

    struct MyStruct

    {

    }

对齐长度的作用在于:如果某个字段的长度大于或等于对齐长度,则对齐长度没用;如果小于对齐长度,则以对齐长度为单元,占用的空间是对齐长度的整数倍,同时保证不大于对齐长度的字段一定分配在同一单元,并且其首地址一定是字段长度的整数倍。

如:

 
  struct MyStruct

    {

        byte a;

        char b;

        int c;

    }

    第0个字节为a,第1个字节无数据,第2,3个字节为b,第4,5,6,7为c。

二、“诡异”的decimal类型

有这样一个结构,请问其占用空间是多少?

 
struct MyStruct

{

    int a;

    deciaml b;

    double c;

}

最初我以为是48个字节,因为int是4个字节,decimal是16个字节,double是8个字节,decimal最大,所以以16个字节对齐,所以是48个字节。

但实际上是32个字节。

这其中的原因在于,decimal是由4个int构成的:

 
struct Decimal

{

    private int flags;

    private int hi;

    private int lo;

    private int mid;

.....//其他不占据对象内存的成员

}

所以上述结构中占内存最大的成员是double,对齐长度是8

三、.Net中实现C语言的Union

可以通过下面的自定义字段位置的方法,在.Net中实现C风格的Union

 
    [StructLayout(LayoutKind.Explicit)]

    struct MyStruct

    {

        [FieldOffset(0)]

        int a;

        [FieldOffset(2)]

        short b;

        [FieldOffset(3)]

        byte c;

    }

从0开始计数,第2个字节为a,b共用,第3个字节为a,b,c共用。
分享到:
评论

相关推荐

    C#结构体指针的定义及使用详解

    - `MarshalAs`属性用于指定结构体成员的内存布局和类型转换规则,这对于与非托管代码交互时非常重要。 - 结构体成员的顺序决定了它们在内存中的排列顺序。 #### C#结构体指针的定义 在C#中,指针不是默认支持的...

    c#结构体和byte之间的转换

    下面将详细介绍如何在C#中实现这种转换,特别是当结构体内部包含数组时。 首先,我们需要了解结构体到字节数组的转换。这个过程称为序列化(Serialization)。C# 提供了多种方法来实现序列化,其中最简单的是使用`...

    C#结构体和C++字节数组的转换

    本文将详细介绍如何在C#中实现结构体与字节数组之间的转换。 首先,我们需要在C#中定义一个结构体,以便能够存储我们要传递的数据。这里的关键是使用`System.Runtime.InteropServices`命名空间,并通过`...

    网络通信中C、C++结构体转C#结构体.rar

    当我们需要在C或C++系统与C#系统之间进行通信时,可能会遇到一个问题:不同编程语言中的数据类型和内存布局可能存在差异。本文将深入探讨如何在网络通信中将C/C++的结构体转换为C#的结构体。 首先,让我们理解C和...

    C++结构体/函数定义转换C#函数定义/结构体

    总之,从C++到C#的转换涉及类型映射、结构体布局、函数签名定义等多个方面。通过理解两种语言之间的差异,以及利用适当的工具,我们可以有效地完成这种转换。在实际操作中,还需要注意平台兼容性、异常处理、内存...

    c# 调用c++对于字符串与复杂结构体的处理

    复杂结构体的处理更为复杂,因为它们涉及到内存布局和生命周期管理。C++/CLI可以创建托管的C++类,这些类可以直接被C#引用。例如,假设有一个C++结构体: ```cpp struct Person { char* name; int age; }; ``` ...

    C#调用C++生成的DLL,并返回结构体引用或者结构体指针多个值

    C#结构体应该具有相同的字段布局和顺序。例如: ```csharp [StructLayout(LayoutKind.Sequential)] public struct MyStruct { public int Value1; public double Value2; [MarshalAs(UnmanagedType.ByValTStr...

    C#byte数组结构体互相转换示例.zip

    这里的`[StructLayout(LayoutKind.Sequential)]`属性确保结构体成员按照声明的顺序进行布局,这对于字节序列化至关重要。 2. **结构体转字节数组**:创建一个方法用于将结构体实例转换为字节数组。 ```csharp ...

    C#调用C++结构体开发

    在C#中,结构体与C++中的结构体有所不同,所以我们需要使用`StructLayout`和`MarshalAs`来匹配C++的布局: ```csharp // DllUse/DllUse.cs using System; using System.Runtime.InteropServices; [StructLayout...

    C# 与 C++ 数据类型比较及结构体转换

    对于C++中的结构体,可以直接在C#中创建对应的结构体,并且注意使用`MarshalAs`属性来确保正确的内存布局和类型转换。 #### 示例 假设有一个C++结构体如下所示: ```cpp struct Point { int x; int y; }; ``` ...

    C#调用C++ Dll关于结构体数组引用的传递及解析使用的展示代码

    本文将详细介绍如何在C#中正确地调用一个C++ DLL,特别是关注于结构体数组的传递及解析。 #### C++ DLL定义 首先,我们来看一下C++ DLL中定义的结构体和函数。这是C#能够正确调用的基础。 ```cpp #ifndef __SDK__...

    C#实现共享内存通讯交互

    结构体的布局必须与内存布局一致,所以通常使用`LayoutKind.Sequential`。 2. **共享内存的创建**: 使用`CreateFileMapping`函数创建一个文件映射对象,然后指定一个空的文件句柄(如`IntPtr.Zero`)以及一些...

    C#向C++封送结构体数组[归类].pdf

    这里使用`LayoutKind.Sequential`布局,确保C#结构体与C++结构体的内存布局一致。`MarshalAs`属性用于指定如何封送字段,例如`UnmanagedType.ByValTStr`用于字符串,`UnmanagedType.ByValArray`用于数组。 然而,...

    C#中调用C++中动态链接库DLL中的结构体

    可以使用`Marshal.AllocHGlobal`来分配内存,然后使用`Marshal.StructureToPtr`将C#结构体复制到该内存中。调用函数后,使用`Marshal.PtrToStructure`将结果复制回C#结构体,并记得释放内存。 ```csharp MyStruct...

    C#调用C++封装成DLL的结构体及类库.rar

    2. **结构体(Struct)**:C#和C++都支持结构体,但它们在内存布局上有所不同。在C#中,结构体是值类型,而在C++中,结构体可以像类一样使用。当C#调用C++ DLL时,需要确保结构体的内存布局与C++相同,包括对齐方式...

    C#与C++通讯字节流转换结构体

    在C++的头文件定义中,使用了`#pragma pack 1`字节对齐,所以C#的结构体也必须要加上对应的特性,`LayoutKind.Sequential`属性让结构体在导出到非托管内存时按出现的顺序依次布局,而对于C++的char数组类型,C#中...

    c#游戏内存修改示例代码

    4. **内存地址计算**:在找到目标值的内存地址后,考虑到内存地址可能会因为各种原因(如ASLR、基址偏移)而变化,需要理解游戏的内存布局和数据结构,计算出相对稳定的指针地址。 5. **内存修改**:一旦找到正确的...

    C#物理内存检测

    本文将深入解析如何利用C#语言进行物理内存检测,通过分析提供的代码片段,我们将详细了解其工作原理、结构布局以及具体实现方法。 ### C#物理内存检测:基本概念 物理内存,即计算机系统中实际安装的RAM(随机...

    C# Struct的内存布局问题解答

    本篇文章将详细探讨C# Struct的内存布局问题。 首先,C#编译器会为Struct添加`LayoutKind.Sequential`属性,而对于Class,则添加`LayoutKind.Auto`。Sequential布局意味着结构体成员会按照声明的顺序依次存储,而...

    VB和VC 结构体Dll参数传递

    VB.NET的结构体(Structure)与VC++的结构体(struct)在内存布局上有所不同,这可能导致在跨语言调用DLL时的数据对齐问题。 1. 数据对齐:VB.NET默认的数据对齐是8字节,而VC++可以设置为4字节或8字节。如果不匹配...

Global site tag (gtag.js) - Google Analytics