zoukankan      html  css  js  c++  java
  • 关于[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] 的解释

    关于[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] 的解释

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] 

    这是C#引用非托管的C/C++的DLL的一种定义定义结构体的方式,主要是为了内存中排序,LayoutKind有两个属性Sequential和Explicit

    Sequential表示顺序存储,结构体内数据在内存中都是顺序存放的Explicit表示精确布局,需要用FieldOffset()设置每个成员的位置这都是

    为了使用非托管的指针准备的,知道什么意思就行,C#的CLR提供了更为灵活的自动管理方式,所以对C#来说可有可无。

    CharSet=CharSet.Ansi表示编码方式

    http://blog.csdn.net/masterft/article/details/1699009

    http://www.cnblogs.com/lonelyDog/archive/2012/02/02/2335432.html

    http://www.cnblogs.com/namek/archive/2010/08/26/1808773.html

    1.Sequential,顺序布局,比如
    struct S1
    {
      int a;
      int b;
    }
    那么默认情况下在内存里是先排a,再排b
    也就是如果能取到a的地址,和b的地址,则相差一个int类型的长度,4字节
    [StructLayout(LayoutKind.Sequential)] 
    struct S1
    {
      int a;
      int b;
    }
    这样和上一个是一样的.因为默认的内存排列就是Sequential,也就是按成员的先后顺序排列.
    2.Explicit,精确布局
    需要用FieldOffset()设置每个成员的位置
    这样就可以实现类似c的公用体的功能
    [StructLayout(LayoutKind.Explicit)] 
    struct S1
    {
      [FieldOffset(0)]
      int a;
      [FieldOffset(0)]
      int b;
    }
    这样a和b在内存中地址相同 
        
      StructLayout特性支持三种附加字段:CharSet、Pack、Size。     
    ·   CharSet定义在结构中的字符串成员在结构被传给DLL时的排列方式。可以是Unicode、Ansi或Auto。     
      默认为Auto,在WIN   NT/2000/XP中表示字符串按照Unicode字符串进行排列,在WIN   95/98/Me中则表示按照ANSI字符串进行排列。     
    ·   Pack定义了结构的封装大小。可以是1、2、4、8、16、32、64、128或特殊值0。特殊值0表示当前操作平台默认的压缩大小。

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct LIST_OPEN
        {
            public int dwServerId;
            public int dwListId;
            public System.UInt16 wRecordSize;
            public System.UInt16 wDummy;
            public int dwFileSize;
            public int dwTotalRecs;
            public NS_PREFETCHLIST sPrefetch;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
            public string szSrcMach;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
            public string szSrcComp;
        }

    此例中用到MashalAs特性,它用于描述字段、方法或参数的封送处理格式。用它作为参数前缀并指定目标需要的数据类型。
    例如,以下代码将两个参数作为数据类型长指针封送给 Windows API 函数的字符串 (LPStr): 
    [MarshalAs(UnmanagedType.LPStr)] 
    String existingfile; 
    [MarshalAs(UnmanagedType.LPStr)] 
    String newfile; 
    注意结构作为参数时候,一般前面要加上ref修饰符,否则会出现错误:对象的引用没有指定对象的实例。
    [ DllImport( "kernel32", EntryPoint="GetVersionEx" )] 
    public static extern bool GetVersionEx2( ref OSVersionInfo2 osvi );

    结论:
            默认(LayoutKind.Sequential)情况下,CLR对struct的Layout的处理方法与C/C++中默认的处理方式相同,即按照结构中占用空间最大的成员进行对齐(Align);
            使用LayoutKind.Explicit的情况下,CLR不对结构体进行任何内存对齐(Align),而且我们要小心就是FieldOffset;
            使用LayoutKind.Auto的情况下,CLR会对结构体中的字段顺序进行调整,使实例占有尽可能少的内存,并进行4byte的内存对齐(Align)。

     

    最后一个是比较详细的介绍了平台调用的结构体对齐和内存布局

    第二:特殊的情况下,C++代码使用#pragma pack(n)改变了边界对齐。这里要使用C#要使用   [StructLayout(LayoutKind.Sequential, Pack = N)] 对齐,否则出错。

    http://www.cnblogs.com/namek/archive/2010/08/26/1808773.html

  • 相关阅读:
    Linux 下的类似Windows下Everything的搜索工具
    windows和linux环境下制作U盘启动盘
    程序调试手段之gdb, vxworks shell
    LeetCode 1021. Remove Outermost Parentheses (删除最外层的括号)
    LeetCode 1047. Remove All Adjacent Duplicates In String (删除字符串中的所有相邻重复项)
    LeetCode 844. Backspace String Compare (比较含退格的字符串)
    LeetCode 860. Lemonade Change (柠檬水找零)
    LeetCode 1221. Split a String in Balanced Strings (分割平衡字符串)
    LeetCode 1046. Last Stone Weight (最后一块石头的重量 )
    LeetCode 746. Min Cost Climbing Stairs (使用最小花费爬楼梯)
  • 原文地址:https://www.cnblogs.com/leijiangtao/p/12081783.html
Copyright © 2011-2022 走看看