貌似传统方法,只能到取结构类型的:
http://topic.csdn.net/u/20090825/16/725bc96a-33f9-4c63-85ef-01d22d6c1ed2_3.html
说明见:292楼~~using System;
namespace ConsoleApplication9
{
    public struct BofStruct { }
    public class BofClass { }
    class Program
    {
        unsafe static void Main(string[] args)
        {
            //--准备
            BofStruct bs = new BofStruct();
            BofClass bc = new BofClass();            //--测试
            //Console.WriteLine("BofStruct'sizeof:{0}", sizeof(BofClass));
            //无法获取托管类型(“BofClass”)的地址和大小,或无法声明指向它的指针
            Console.WriteLine("BofStruct'sizeof:{0}", sizeof(BofStruct));
            //BofStruct'sizeof:4
            //Console.WriteLine("bc'pointer:{0:X8}", (uint)&bc);
            //无法获取托管类型(“BofClass”)的地址和大小,或无法声明指向它的指针
            Console.WriteLine("bc'pointer:{0:x8}", (uint)&bs);
            //bc'pointer:057fecd0            //--使用
            int num;
            int* p;
            p = #
            *p = 999;
            System.Console.WriteLine("p:{0}", *p);
            System.Console.WriteLine("p:{0}", p->ToString());            Console.ReadKey();
        }
    }
}也许也有别的方法吧~~

解决方案 »

  1.   

    class类的指针==引用啊>???为什么要绕圈子呢?
      

  2.   


    指针类型不同于引用类型,
    当中要架起一座桥梁才行.在.net框架中,能够实施指针操作的类举不胜举
    包括引入一些特定的类也行,
    只是我并不熟这部分内容...
      

  3.   


    请看这个问题,需要这样做
    http://topic.csdn.net/u/20090904/21/639bdc71-16e8-48e8-9528-04c0b985dfdc.html?seed=2135148115&r=59581132#r_59581132
      

  4.   

    指针类型中,在 * 前面指定的类型称为该指针类型的目标类型 (referent type)。它表示该指针类型的值所指向的变量的类型。
    与引用(引用类型的值)不同,指针不受垃圾回收器跟踪(垃圾回收器并不知晓指针和它们指向的数据)。出于此原因,不允许指针指向引用或者包含引用的结构,并且指针的目标类型必须是 unmanaged-type。
    unmanaged-type 是任何不是 reference-type 并且在任何嵌套级别都不包含 reference-type 字段的类型。换句话说,unmanaged-type 是下列类型之一:
    • sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal 或 bool。
    • 任何 enum-type。
    • 任何 pointer-type。
    • 任何由用户定义的只包含 unmanaged-types 字段的 struct-type。
    将指针和引用进行混合使用时的基本规则是;引用(对象)的目标可以包含指针,但指针的目标不能包含引用。
      

  5.   

    @健健不一定要把引用类型转成指针类型,有没有办法,获得引用类型的地址.哪怕是一些非常规的办法,比如直接从内存中找,或者过外部程序(比如用C++)或者能够得知一连串引用类型地址的先后顺序也行.GC方法有没有办法,我还没有研究过.总之,办法肯定是有的,不限定在C#中(但必须是C#的程序集.)
      

  6.   

    类对象是可以移动的,所以不能获取其地址如果你非要获取,可以参考这个方法:
    fixed类中的第一字段,然后取得该字段的地址但是我想这个类的内存布局不能是Auto,只能是按顺序或显式布局吧
      

  7.   


    fixed 语句中声明的局部变量类型必须是指针类型既然这样,又回到老问题上,针类型无法与class类型沟通
      

  8.   

    奇怪的是System.objcet类就能做到public virtual int GetHashCode()
    {
        return MultiUseWord.GetHashCode(this);
    }具体执行在辅助类中:
    MultiUseWord
    这个类太复杂了,
    不好调式,
    也看不明白.
      

  9.   

    我们来看一下,object的指针是如何被传递的.
    (这个解决不了问题,只能用于分析)------------值的传递过程----------------
    [1]传入对象,获得对象muw,在muw上调用GetPayload
    MultiUseWord muw = GetForObject(obj);[2]获得muw
    muw.GetPayload()
    实际上来自于MultiUseWord的preHeader.muw
    get { return this.preHeader.muw; }[2]GetPayload将对象的value进行掩码并返回
    UIntPtr PAYLOAD_MASK = (UIntPtr)0xfffffff8;
    UIntPtr result = (this.value & PAYLOAD_MASK);
    result就是我们要的值,关键还是这个this的转换过程------------this的转换过程----------------
    [1]传入对象obj
    MultiUseWord muw = GetForObject(obj);[2]对象强制转换为ObjectPreMUW
    MultiUseWord result = ((ObjectPreMUW)obj).muw;[3]ObjectPreMUW
    ObjectPreMUW继承了ObjectMUW
    internal class ObjectPreMUW : ObjectMUW
    字段
    internal new PreHeaderDefault preHeader;[4]PreHeaderDefault
    internal MultiUseWord muw;[5]指针的值
    internal UIntPtr value;翻遍Object也没有这个指针值,
    鬼知道怎么传过去的,
    又是编译器魔法吧-_-
      

  10.   

    http://pinvoke.net/default.aspx/advapi32/ConvertStringSidToSid.html
      

  11.   

    [1]unsafe加fixed语法可以取得struct的一个指针。
    [2]不使用unsafe语法,用Marshal.PtrToStructure也应该可以,不过需要Copy内存两次
    [3]与引用(引用类型的值)不同,指针不受垃圾回收器跟踪(垃圾回收器不了解指针和它们指向的数据)。
    出于此原因,不允许指针指向引用或者包含引用的结构,并且指针的目标类型必须是非托管类型。
    [4]“非托管类型”是任何不是“引用类型”并且在任何嵌套级别都不包含“引用类型”字段的类型。
    [A]sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal 或 bool。
    [B]任何“枚举类型”。
    [C]任何“指针类型”。
    [D]任何由用户定义的只包含“非托管类型”字段的“结构类型”。
    [5]void* 类型表示指向未知类型的指针。
    由于目标类型是未知的,间接寻址运算符不能应用于 void* 类型的指针,
    也不能对这样的指针执行任何算术运算。
    但是 void* 类型的指针可以强制转换为任何其他指针类型(反之亦然)。
    [6]允许在不同指针类型之间以及指针类型与整型之间进行转换。
    [7]指针类型可用作易失字段的类型
    [8]方法可以返回某一类型的值,而该类型可以是指针。
    [9]stackalloc 运算符可用于从调用堆栈中分配内存。
    [10]fixed 语句可用于暂时固定一个变量,以便可以获取它的地址 
      

  12.   

    using System;
    using System.Collections;
    using System.Runtime.InteropServices;public unsafe class Memory
    {
        // Handle for the process heap. This handle is used in all calls to the
        // HeapXXX APIs in the methods below.
        static int ph = GetProcessHeap();
        // Private instance constructor to prevent instantiation.
        private Memory() { }
        // Allocates a memory block of the given size. The allocated memory is
        // automatically initialized to zero.
        public static void* Alloc(int size)
        {
            void* result = HeapAlloc(ph, HEAP_ZERO_MEMORY, size);
            if (result == null) throw new OutOfMemoryException();
            return result;
        }
        // Copies count bytes from src to dst. The source and destination
        // blocks are permitted to overlap.
        public static void Copy(void* src, void* dst, int count)
        {
            byte* ps = (byte*)src;
            byte* pd = (byte*)dst;
            if (ps > pd)
            {
                for (; count != 0; count--) *pd++ = *ps++;
            }
            else if (ps < pd)
            {
                for (ps += count, pd += count; count != 0; count--) *--pd = *--ps;
            }
        }
        // Frees a memory block.
        public static void Free(void* block)
        {
            if (!HeapFree(ph, 0, block)) throw new InvalidOperationException();
        }
        // Re-allocates a memory block. If the reallocation request is for a
        // larger size, the additional region of memory is automatically
        // initialized to zero.
        public static void* ReAlloc(void* block, int size)
        {
            void* result = HeapReAlloc(ph, HEAP_ZERO_MEMORY, block, size);
            if (result == null) throw new OutOfMemoryException();
            return result;
        }
        // Returns the size of a memory block.
        public static int SizeOf(void* block)
        {
            int result = HeapSize(ph, 0, block);
            if (result == -1) throw new InvalidOperationException();
            return result;
        }
        // Heap API flags
        const int HEAP_ZERO_MEMORY = 0x00000008;
        // Heap API functions
        [DllImport("kernel32")]
        static extern int GetProcessHeap();
        [DllImport("kernel32")]
        static extern void* HeapAlloc(int hHeap, int flags, int size);
        [DllImport("kernel32")]
        static extern bool HeapFree(int hHeap, int flags, void* block);
        [DllImport("kernel32")]
        static extern void* HeapReAlloc(int hHeap, int flags,
           void* block, int size);
        [DllImport("kernel32")]
        static extern int HeapSize(int hHeap, int flags, void* block);
    }class Test
    {
        unsafe static void Main()
        {
            byte[] array = new byte[256];
            fixed (byte* p = array) Console.WriteLine("array'address :{0:X8}", (uint)p);
            Console.WriteLine("array'hashcode:{0:X8}", array.GetHashCode());
            byte* buffer = (byte*)Memory.Alloc(256);
            for (int i = 0; i < 256; i++) buffer[i] = (byte)i;
            fixed (byte* p = array) Memory.Copy(buffer, p, 256);
            Memory.Free(buffer);
            
            //for (int i = 0; i < 256; i++) Console.WriteLine(array[i]);
            Console.ReadKey();
        }
    }
      

  13.   

    有一点小小的突破:string 类型是可以的,不过没有推广价值。
    因为string是自定义引用类型,被特殊照顾了,
    主要是看在类似于“字符数组”的结构上。using System;struct B
    {
        int i;
        //int[] o;
        //TODO:
    }class MyClass
    {
        unsafe static void Main(string[] args)
        {
            B[] a = { new B(), new B(), new B() };
            System.Console.WriteLine(sizeof(B));
            string s = "12345";
            fixed (char* p = s) System.Console.WriteLine("{0:X8}", (uint)p);        int b = 100;
            System.Console.WriteLine("{0:X8}", (uint)&b);        System.Console.ReadKey();
        }
    }
      

  14.   

    三种情况可以获取指针:T:为非托管类型
    [1]T
    [2]T[]
    [3]string而托管类型(除数组、string)以外的类型变量,
    获到地址,不应该要指针的身上打主意了。以下的方法
    [1]语言混合编程
    [2]DllImport系统调用
    [3]反推(从hashcode值反推也是一种思路)
    [4]Marshal
     
      

  15.   

    补一个MSDN上申请栈的例子(对应上面堆的申请)using System;
    class Test
    {
       static string IntToString(int value) {
          int n = value >= 0? value: -value;
          unsafe {
             char* buffer = stackalloc char[16];
             char* p = buffer + 16;
             do {
                *--p = (char)(n % 10 + '0');
                n /= 10;
             } while (n != 0);
             if (value < 0) *--p = '-';
             return new string(p, 0, (int)(buffer + 16 - p));
          }
       }
       static void Main() {
          Console.WriteLine(IntToString(12345));
          Console.WriteLine(IntToString(-999));
       }
    }
      

  16.   

    在c#中调用virtualqueryex(api接口)!在win32中,每个应用程序都可“看见”4gb的线性地址空间,其中最开始的4mb和最后的2gb由操作系统保留,剩下不足2gb的空间用于应用程序私有空间。具体分配如下:0xffffffff-0xc0000000的1gb 用于vxd、存储器管理和文件系统;0xbfffffff- 0x80000000的1gb用于共享的win32 dll、存储器映射文件和共享存储区;0x7fffffff-0x00400000为每个进程的win32专用地址;0x003fffff- 0x00001000为ms-dos 和 win16应用程序;0x00000fff-0x00000000为防止使用空指针的4,096字节。以上都是指逻辑地址,也就是虚拟内存。
    虚拟内存通常是由固定大小的块来实现的,在win32中这些块称为“页”,每页大小为4,096字节。在intel cpu结构中,通过在一个控制寄存器中设置一位来启用分页。启用分页时cpu并不能直接访问内存,对每个地址要经过一个映射进程,通过一系列称作“页表” 的查找表把虚拟内存地址映射成实际内存地址。通过使用硬件地址映射和页表win32可使虚拟内存即有好的性能而且还提供保护。利用处理器的页映射能力,操作系统为每个进程提供独立的从逻辑地址到物理地址的映射,使每个进程的地址空间对另一个进程完全不可见。win32中也提供了一些访问进程内存空间的函数,但使用时要谨慎,一不小心就有可能破坏被访问的进程。virtualqueryex
    函数功能描述:查询地址空间中内存地址的信息。函数原型:
    dword virtualqueryex( handle hprocess, lpcvoid lpaddress, pmemory_basic_information lpbuffer, dword dwlength );
    参数:
       hprocess    进程句柄。
       lpaddress   查询内存的地址。
       lpbuffer    指向memory_basic_information结构的指针,用于接收内存信息。
       dwlength    memory_basic_information结构的大小。
    返回值:
       函数写入lpbuffer的字节数,如果不等于sizeof(memory_basic_information)表示失败。
    备注:
       memory_basic_information在winnt.h中定义如下:
           typedef struct _memory_basic_information {
               pvoid baseaddress;       // 区域基地址。
               pvoid allocationbase;    // 分配基地址。
               dword allocationprotect; // 区域被初次保留时赋予的保护属性。
               size_t regionsize;       // 区域大小(以字节为计量单位)。
               dword state;             // 状态(mem_free、mem_reserve或 mem_commit)。
               dword protect;           // 保护属性。
               dword type;              // 类型。
           } memory_basic_information, *pmemory_basic_information;成员解释:
     baseaddress              与lpaddress参数的值相同,但是四舍五入为页面的边界值。
     allocationbase           指明用virtualalloc函数分配内存区域的基地址。lpaddress
                              在该区域之内。
     allocationprotect        指明该地址空间区域被初次保留时赋予该区域的保护属性。
     page_readonly            只读属性,如果试图进行写操作,将引发访问违规。如果系统
                              区分只读、执行两种属性,那么试图在该区域执行代码也将引
                              发访问违规。
     page_readwrite           允许读写。
     page_execute             只允许执行代码,对该区域试图进行读写操作将引发访问违规。
     page_execute_read        允许执行和读取。
     page_execute_readwrite   允许读写和执行代码。
     page_execute_writecopy   对于该地址空间的区域,不管执行什么操作,都不会引发访问违
                              规。如果试图在该页面上的内存中进行写入操作,就会将它自己
                              的私有页面(受页文件的支持)拷贝赋予该进程。
     page_guard               在页面上写入一个字节时使应用程序收到一个通知(通过一个异
                              常条件)。该标志有一些非常巧妙的用法。windows 2000在创建
                              线程堆栈时使用该标志。
     page_noaccess            禁止一切访问。
     page_nocache             停用已提交页面的高速缓存。一般情况下最好不要使用该标志,
                              因为它主要是供需要处理内存缓冲区的硬件设备驱动程序的开发
                              人员使用的。
     regionsize               用于指明内存块从基地址即baseaddress开始的所有页面的大
                              小(以字节为计量单位)这些页面与含有用lpaddress参数设
                              定的地址的页面拥有相同的保护属性、状态和类型。
     state                    用于指明所有相邻页面的状态。
     mem_commit               指明已分配物理内存或者系统页文件。
     mem_free                 空闲状态。该区域的虚拟地址不受任何内存的支持。该地址空间没
                              有被保留。改状态下allocationbase、allocationprotect、protect
                              和type等成员均未定义。
            mem_reserve       指明页面被保留,但是没有分配任何物理内存。该状态下protect成
                              员未定。
        protect               用于指明所有相邻页面(内存块)的保护属性。这些页面与含有
                              拥有相同的保属性、状态和类型。意义同allocationprotect。
        type                  用于指明支持所有相邻页面的物理存储器的类型(mem_image,
                              mem_mapped或mem_private)。这些相邻页面拥有相同的保护属
                              性、状态和类型。如果是windows 98,那么这个成员将总是
                              mem_private 。
           mem_image         指明该区域的虚拟地址原先受内存映射的映像文件(如.exe或dll
                             文件)的支持,但也许不再受映像文件的支持。例如,当写入模块
                             映像中的全局变量时,“写入时拷贝”的机制将由页文件来支持特
                             定的页面,而不是受原始映像文件的支持。
           mem_mapped        该区域的虚拟地址原先是受内存映射的数据文件的支持,但也许不
                             再受数据文件的支持。例如,数据文件可以使用“写入时拷贝”的
                             保护属性来映射。对文件的任何写入操作都将导致页文件而不是原
                             始数据支持特定的页面。
           mem_private       指明该内存区域是私有的。不被其他进程共享。
    c#怎样调用api不用 说了吧
    更简单的方法:
    每隔一定时间,抓取屏幕截屏,分析指定位置的颜色值,然后... 
      

  17.   

    搞到后面不知道你问什么了,对于你前一个问题,确实是没有必要的,虽然引用说会分配同一个地址,其实C++也会,但是需要前一个地址已经作废的情况下,那么系统才进行重新分配,这个重新分配,其他类都可能会重新分配到这个地址里面,即使分配到同一个地址下,地址下的数据实际调用时会被重写,不要认为分配到同个地址下,那些数据就会被系统保存下作为新类的数据而使用。
    另外试下Marshal.GetComInterfaceForObject是否得到你需要的
      

  18.   

    多谢@zhujiechang通过Marshal来解决问题的希望也比较渺茫。using System;
    using System.Runtime.InteropServices;
    //换成struct正常
    public class Point
    {
        public int x;
        public int y;
    }
    class Example
    {
        static void Main()
        {
            Point p = new Point();
            p.x = 1;
            p.y = 1;
            //未处理的异常:  System.ArgumentException: 类型“Point”不能作为非托管结构进行封送
            //处理;无法计算有意义的大小或偏移量。
            IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(p));
            Marshal.StructureToPtr(p, pnt, false);
            Point anotherP = new Point();
            anotherP = (Point)Marshal.PtrToStructure(pnt, typeof(Point));
            Console.WriteLine("The value of new point is " + anotherP.x + " and " + anotherP.y + ".");
            Marshal.FreeHGlobal(pnt);
        }
    }现在的思路是,退一步,
    [1]定义一个引用类型
    [2]Marshal申请一个内存,保留指针
    [3]将引用类型封送到该内存上把命题反过来,
    己知地址,将引用类型放置到该地址上
      

  19.   

    多少还有点希望,想办法绕过sizeofusing System;
    using System.Runtime.InteropServices;
    class Test
    {
        public static unsafe byte[] Struct2Bytes(Object obj)
        {
            int size = Marshal.SizeOf(obj);
            byte[] bytes = new byte[size];
            IntPtr arrPtr = Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0);
            Marshal.StructureToPtr(obj, arrPtr, true);
            return bytes;
        }    public static unsafe Object Bytes2Struct<T>(byte[] bytes)
            //where T:struct
        {
            IntPtr arrPtr = Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0);
            return Marshal.PtrToStructure(arrPtr, typeof(T));
        }
    }class TestA
    {
        static void Main(string[] args)
        {
            int s = 100;
            byte[] bytes = Test.Struct2Bytes(s);
            object o = Test.Bytes2Struct<int>(bytes);
            Console.WriteLine(o.GetType());
            Console.WriteLine(o);
        }
    }
      

  20.   

    再突破一小步:using System;
    using System.Runtime.InteropServices;[StructLayout(LayoutKind.Sequential, Pack = 1)]
    public class Point
    {
        public int x;
        public int y;
    }class Example
    {
        static void Main()
        {
            //类型A
            Point pointA = new Point();
            pointA.x = 100;
            pointA.y = 200;
            
            //从进程的非托管内存中分配内存
            int sizeOfPointA = Marshal.SizeOf(typeof(Point));
            Console.WriteLine("size of Point:{0}", sizeOfPointA);
            IntPtr ptr = Marshal.AllocHGlobal(sizeOfPointA);
            Console.WriteLine("ptr:{0:X8}", (uint)ptr);        //将数据从托管对象封送到非托管内存块
            Marshal.StructureToPtr(pointA, ptr, false);
            pointA.x = 300;
            pointA.y = 400;        //类型B
            Point pointB;// = new Point();
            //Console.WriteLine(pointB.GetHashCode());
            //unsafe
            //{
            //    System.Console.WriteLine("anp:{0:X8}", (uint)&pointB);
            //}        //将数据从非托管内存块封送到新分配的指定类型的托管对象
            pointB = (Point)Marshal.PtrToStructure(ptr, typeof(Point));        //释放以前使用从进程的非托管内存中分配的内存
            Marshal.FreeHGlobal(ptr);        //验证
            Console.WriteLine("hashcode of PointA:{0:X8}", pointA.GetHashCode());
            Console.WriteLine("hashcode of PointB:{0:X8}", pointB.GetHashCode());
            Console.WriteLine("The value of new pointA is " + pointA.x + " and " + pointA.y + ".");
            Console.WriteLine("The value of new pointB is " + pointB.x + " and " + pointB.y + ".");
        }
    }
      

  21.   

    还有很多问题要去验证、落实、解决、优化。先总结一下考虑这类问题的思路。
    1)语法思考法阶段
    穷尽语法,从语法的层面上去偿试。
    比如,这里面需要解决指针的问题,
    就把整个指针研究一遍。
    反复对比可行性与不可行性。
    在个CASE中,结构类型可以做到,引用类型就做不到。
    比较严谨的提法应该是:委托类型与非委托类型(并不等同于结构类型)
    重点放在做不到的根源上,为什么不行?!
    我总结了一下,主要出于两个原因:
    [A]委托类型的内存对齐是不确定的,由编译器决定的(从一些出错信息中得到提示)
    [B]基于A,委托类型的大小很难取得(后来发现这个是需要一些技术手段来处理的,从C++.net中获得灵感)
    [C]委托类型分配在堆上,受到GC的影响,并且地址本身就是不可靠的。(先考虑了为啥C#要设计出fixed来)2)语言对比阶段
    主要研究了C++语法机制,
    一编关于C#直接调用汇编给予了一些灵感
    总结如下:
    [A]委托类型的内存布局是关键
    [B]解决了sizeof的问题,就能终绕过这个东西,就可以突破非委托类型的桎梏。C++的关键也在尺寸上。3)技术筛选阶段
    设定包围圈
    [1]语言混合编程
    [2]DllImport系统调用
    [3]反推(hashcode值/显存关系)
    [4]Marshal 
    最后还是决定先从Marshal偿试突破
    Marshal整个学习一遍,发现了几个关键点:
    [A]内存布局StructLayout(在class上试了一下,竟然也行,信心大增)
    [B]内存机制GC,发现GC存在地址转换机制
    [C]Marshal本身包围圈己经缩的很小了,
    因为需要再找一些验证手段,答案明天公布,
    也并非100%的,但多少还有点价值。
      

  22.   

    代码并不完善,要解决的问题更多了。包括:class在堆上不是简单的几个字段,比如TypeHandle和SyncBlockIndex
    简单测试代码:
    using System;
    using System.Runtime.InteropServices;public class BoxedObject : IDisposable
    {
        private object _boxedObject;
        private GCHandle _memData;    public BoxedObject(object boxObject)
        {
            if (boxObject == null)
            {
                throw new ArgumentNullException();
            }
            _boxedObject = boxObject;
        }    ~BoxedObject()
        {
            (this as IDisposable).Dispose();
        }    public object Value
        {
            get { return _boxedObject; }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException();
                }
                if (value.GetType() != _boxedObject.GetType())
                {
                    throw new NotSupportedException(string.Format("Can not set [{0}] value to [{1}] object",
                        value.GetType().Name,
                        _boxedObject.GetType().Name));
                }            if (!_memData.IsAllocated)
                {
                    _memData = GCHandle.Alloc(_boxedObject);
                }
                IntPtr pMemData = GCHandle.ToIntPtr(_memData);
                IntPtr pBox = new IntPtr((Marshal.ReadIntPtr(pMemData).ToInt64() + IntPtr.Size));
                Marshal.StructureToPtr(value, pBox, false);
            }
        }    void IDisposable.Dispose()
        {
            if (_memData.IsAllocated)
                _memData.Free();
        }
    }class Program
    {
        static void Main1(string[] args)
        {
            object test = 100;
            Console.WriteLine("original value=" + test.ToString() + ", hash=" + test.GetHashCode());
            BoxedObject b = new BoxedObject(test);
            b.Value = 1000;
            Console.WriteLine("after edit value=" + test.ToString() + ", hash=" + test.GetHashCode());        Console.ReadKey();
        }
    }
      

  23.   

    上段代码是后来发现的,异曲同工,关于装箱的值类型,MARK一下:测试代码:
    using System;
    using System.Runtime.InteropServices;[StructLayout(LayoutKind.Sequential, Pack = 1)]
    class MyClass
    {
        public int x ;
        public byte y ;
    }struct MyStruct
    {
        public int x;
        public int y;
    }class Tools
    {
        public static IntPtr GetAddress<T>(object obj)
        {
            GCHandle gch = new GCHandle();
            if (!gch.IsAllocated)
            {
                gch = GCHandle.Alloc(obj);
            }
            IntPtr ptr_ptr_obj = GCHandle.ToIntPtr(gch);
            IntPtr ptr_obj = Marshal.ReadIntPtr(ptr_ptr_obj);        return ptr_obj;
        }    public static int GetSizeOf<T>()
        {
            int size = Marshal.SizeOf(typeof(T));
            return size;
        }
    }class ProgramA
    {
        static void Main(string[] args)
        {
            //Class Test
            MyClass mc = new MyClass();
            IntPtr mc_prt = Tools.GetAddress<MyClass>(mc);
            int mc_size = Tools.GetSizeOf<MyClass>();        Console.WriteLine("==========Class Test==========");
            Console.WriteLine("mc's sizeof:{0}", mc_size);
            Console.WriteLine("mc's address :{0:X8}", mc_prt.ToString());
            Console.WriteLine("mc's hashcode:{0:X8}", mc.GetHashCode());        //Struct Test
            MyStruct ms = new MyStruct();
            IntPtr ms_prt = Tools.GetAddress<MyStruct>(ms);
            int ms_size = Tools.GetSizeOf<MyStruct>();        Console.WriteLine("==========Struct Test==========");
            Console.WriteLine("ms's sizeof:{0}", ms_size);
            Console.WriteLine("ms's address :{0:X8}", ms_prt.ToString());
            Console.WriteLine("ms's hashcode:{0:X8}", ms.GetHashCode());        //string Test
            string ss = "abc";
            IntPtr ss_prt = Tools.GetAddress<string>(ss);
            //int ss_size = Tools.GetSizeOf<string>();        Console.WriteLine("==========string Test==========");
            //Console.WriteLine("ss's sizeof:{0}", ss_size);
            Console.WriteLine("ss's address :{0:X8}", ss_prt.ToString());
            Console.WriteLine("ss's hashcode:{0:X8}", ss.GetHashCode());        //Class Test
            MyClass mc1 = new MyClass();
            IntPtr mc1_prt = Tools.GetAddress<MyClass>(mc1);
            int mc1_size = Tools.GetSizeOf<MyClass>();        Console.WriteLine("==========Class Test==========");
            Console.WriteLine("mc1's sizeof:{0}", mc1_size);
            Console.WriteLine("mc1's address :{0:X8}", mc1_prt.ToString());
            Console.WriteLine("mc1's hashcode:{0:X8}", mc1.GetHashCode());        //Array Test
            MyClass[] mcs = new MyClass[3] { new MyClass(), new MyClass(), new MyClass(), };
            Console.WriteLine("==========Array Test==========");
            Console.WriteLine("mcs[0]'s address :{0:X8}", Tools.GetAddress<MyClass>(mcs[0]).ToString());
            Console.WriteLine("mcs[1]'s address :{0:X8}", Tools.GetAddress<MyClass>(mcs[1]).ToString());
            Console.WriteLine("mcs[2]'s address :{0:X8}", Tools.GetAddress<MyClass>(mcs[2]).ToString());        //Marshal.StructureToPtr(value, pBox, false);        //End
            Console.ReadKey();
        }
    }完善这个过程,交给大家去完成吧,主体思路己经有了。还有许多问题有待解决~~~
      

  24.   

    @ProjectDD
    先去了解一下指针,了解一下Marshal
    也许你会换个看法。没有指针,C#只能做C++10%的事情。
    有了指针,C#能够做C++90%的事情。如果你不打算与其它系统交互,引用类型也许足够了。
    要是你打算涉足图像、游戏、视频、算法、密码、Shell的话,
    看看引用类型还能帮得上忙嘛?
      

  25.   

    这个问题,暂造一段落,
    剩下的问题会相对容易些。
    继续研究GC与内存布局...BTW:
    unsafe并非不全完,而是要求安全(对安全性的配置)
    相比C++,在C#中使用unsafe首先是提高了安全的要求,其次才是提示编程者要小心谨慎。交作业:
    using System;
    using System.Runtime.InteropServices;//32bit计算机
    [StructLayout(LayoutKind.Explicit)]
    class MyClass
    {
        [FieldOffset(0)]
        public char c1 ;
        [FieldOffset(4)]
        public int i1 ;
        [FieldOffset(8)]
        public char c2;
    }struct MyClassLayout
    {
        public ulong SyncblkIndex;//index @ -4
        public ulong TypeHandle;//index @ 0
        public char c1;//index @ 4
        public int i1;//index @ 4
        public char c2;//index @ 4
    }class Tools
    {
        public static IntPtr GetAddress<T>(object obj)
        {
            GCHandle gch = new GCHandle();
            if (!gch.IsAllocated)
            {
                gch = GCHandle.Alloc(obj);
            }
            IntPtr ptr_ptr_obj = GCHandle.ToIntPtr(gch);
            IntPtr ptr_obj = Marshal.ReadIntPtr(ptr_ptr_obj);        return ptr_obj;
        }    public static int GetSizeOf<T>()
        {
            int size = Marshal.SizeOf(typeof(T));
            return size;
        }
    }class ProgramA
    {
        static void GetFields(MyClass obj,ref MyClassLayout layout)
        {
            IntPtr pTypeHandle = Tools.GetAddress<MyClass>(obj);
            IntPtr pSyncblkIndex = new IntPtr(pTypeHandle.ToInt32() - IntPtr.Size);
            IntPtr pC1 = new IntPtr(pTypeHandle.ToInt32() + IntPtr.Size + 0);
            IntPtr pI1 = new IntPtr(pTypeHandle.ToInt32() + IntPtr.Size + 4);
            IntPtr pC2 = new IntPtr(pTypeHandle.ToInt32() + IntPtr.Size + 8);        layout.SyncblkIndex = (ulong)Marshal.PtrToStructure(pSyncblkIndex, typeof(ulong));
            layout.TypeHandle = (ulong)Marshal.PtrToStructure(pTypeHandle,typeof(ulong));
            layout.c1 = (char)Marshal.PtrToStructure(pC1, typeof(char));
            layout.i1 = (int)Marshal.PtrToStructure(pI1, typeof(int));
            layout.c2 = (char)Marshal.PtrToStructure(pC2, typeof(char));
        }    static void SetFields(MyClass obj, ref MyClassLayout layout)
        {
            IntPtr pTypeHandle = Tools.GetAddress<MyClass>(obj);
            IntPtr pSyncblkIndex = new IntPtr(pTypeHandle.ToInt32() - IntPtr.Size);
            IntPtr pC1 = new IntPtr(pTypeHandle.ToInt32() + IntPtr.Size + 0);
            IntPtr pI1 = new IntPtr(pTypeHandle.ToInt32() + IntPtr.Size + 4);
            IntPtr pC2 = new IntPtr(pTypeHandle.ToInt32() + IntPtr.Size + 8);        Marshal.StructureToPtr(layout.SyncblkIndex, pSyncblkIndex, false);
            Marshal.StructureToPtr(layout.TypeHandle, pTypeHandle, false);
            Marshal.StructureToPtr(layout.c1, pC1, false);
            Marshal.StructureToPtr(layout.i1, pI1, false);
            Marshal.StructureToPtr(layout.c2, pC2, false);
        }    static void PrintFields(MyClass obj,string tips)
        {
            int size = Tools.GetSizeOf<MyClass>();        IntPtr pTypeHandle = Tools.GetAddress<MyClass>(obj);
            IntPtr pSyncblkIndex = new IntPtr(pTypeHandle.ToInt32() - IntPtr.Size);
            IntPtr pC1 = new IntPtr(pTypeHandle.ToInt32() + IntPtr.Size + 0);
            IntPtr pI1 = new IntPtr(pTypeHandle.ToInt32() + IntPtr.Size + 4);
            IntPtr pC2 = new IntPtr(pTypeHandle.ToInt32() + IntPtr.Size + 8);        Console.WriteLine("========== " + tips + " ==========");
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("c1:{0:X8},i1:{1:X8},c2:{2:X8}", obj.c1, obj.i1, obj.c2);
            Console.ResetColor();
            Console.WriteLine("MyClass's size:{0}", size);
            Console.Write("MyClass's hashcode:");
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("{0:X8}", obj.GetHashCode());
            Console.ResetColor();
            Console.WriteLine("========== " + "address list" + " ==========");
            Console.WriteLine("SyncblkIndex's address :{0:X8}", (uint)pSyncblkIndex);
            Console.WriteLine("TypeHandle's address :{0:X8}", (uint)pTypeHandle);
            Console.WriteLine("C1's address :{0:X8}", (uint)pC1);
            Console.WriteLine("I1's address :{0:X8}", (uint)pI1);
            Console.WriteLine("C2's address :{0:X8}", (uint)pC2);
            Console.WriteLine();
        }    static void Main(string[] args)
        {
            //创建
            MyClass obj = new MyClass();
            MyClassLayout layout = new MyClassLayout();        //初始化
            obj.c1='a';
            obj.i1 = 100;
            obj.c2='b';
            
            //值-->结构副本
            GetFields(obj, ref layout);
            PrintFields(obj, "修改前");        //修改结构副本
            layout.c1 = '!';
            layout.i1 = 1024-1;
            layout.c2 = '%';
            
            //结构副本-->值
            SetFields(obj, ref layout);
            PrintFields(obj, "修改后");        //结束
            Console.ReadKey();
        }
    }
      

  26.   

    输出结果:========== 修改前 ==========
    c1:a,i1:00000064,c2:b
    MyClass's size:12
    MyClass's hashcode:033C0D9D
    ========== address list ==========
    SyncblkIndex's address :01351730
    TypeHandle's address :01351734
    C1's address :01351738
    I1's address :0135173C
    C2's address :01351740========== 修改后 ==========
    c1:!,i1:000003FF,c2:%
    MyClass's size:12
    MyClass's hashcode:011C7A8C
    ========== address list ==========
    SyncblkIndex's address :01351730
    TypeHandle's address :01351734
    C1's address :01351738
    I1's address :0135173C
    C2's address :01351740
      

  27.   


    那你别在C#版混了,直接回去用C++得了, 图像,游戏,怎么了,C++能做,C#更容易..
    引用本身就是个指针,只是 象指针那样还要去管内存释放... 你不用来故做高深了.
      

  28.   

    @ProjectDD真是无知者无畏啊
    引用本身就是个指针
    这就代表你的水平,这并不代不表C#,
    你也代表不了CSDN啊。
      

  29.   

    User.class 
    Class.forName("PackageName.ClassName");
      

  30.   

    发现这个帖子有进展了,进来回个帖。
    因为内容比较多,代码我就不仔细看了。发现提到了一个Marshal 类,啊,好东西啊,有了那个类,类似指针的操作就不难做到了,其实也就是把地址传递给接口,C#本身不需要直接操作指针的,没有意义。至于楼主后来使用的GCHandle,在Marshal 类中也提到过,MSDN上真的很详细。Marshal 类复制托管资源到非托管资源,而GCHandle可以直接固定托管资源,使其作为非托管资源传递。
      

  31.   

    怎么看着很熟悉,原来这是我自己写的!
    lz引用文章可是需要加出处说明的。
    其实最简单的获得指针的办法是:object data = new object();
    GCHandle handle = GCHandle.Alloc(data);
    void* pVer = handle.AddrOfPinnedObject().ToPointer();
    // do something.
    handle.Free();
      

  32.   

    object data = new object();
    GCHandle handle = GCHandle.Alloc(data);
    void* pVer = handle.AddrOfPinnedObject().ToPointer();
    // do something.
    handle.Free();
      

  33.   


    @lalac
    你看一下48楼顶,我有一段说明的,因为觉得对装箱的值类型理解有帮助,并且重要技术点是一样的,有必要分享一下。(如果有私心的话,完全可以不贴,对不对。)上段代码是后来发现的,异曲同工,关于装箱的值类型,MARK一下: google 关键字:GCHandle StructureToPtr,
    再搜,链接有多个,初始的那个文章作者:winkingz
    内容不错,特别是“装箱的值类型”这个概念被表达清楚的。
    你告诉我确切的链接地址,我会补上的。至于代码确实比较笨拙,这个我也意识到了,
    因为是第一时间贴上来的,一来比较兴奋,二来没有做优化的事情(这个也提了),只要能先达到目标就行,
    后来花点时间把GCH和Marshal整个看了一遍,现在比较清楚了。至于最原始的动机:
    解决"引用类型"的hashcode算法(贴出来的只是一个讨巧做法)
    而现在的目标是模似类似SOS的功能,
    也就是实现:表达引用类型的对象图谱,指针是一个重要的开头,就象是登月上的一小步。当前研究点(net3.5下的布局有点不一样):
    CGInfo
    Flags
    Basic Instance Size
    EEClass
    Interface Vtable Map
    Num Interfaces
    CoreElementType
    Module
    .cctor Slot
    Default .ctor Slot
    Interface Map
    Delegate
    Mum Method Solts希望能够共勉之