欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C#到底有没有指针

程序员文章站 2022-03-27 09:49:33
...

  起因

  C#是有指针的,只不过要先标记unsafe,在Rust语言中也是通过unsafe标记,指针在C#越来越重要,尤其在.Net Core中使用指针也更多,在.Net Core是Unsafe类,有更多指针的操作.

  unsafe并不是不安全的,只是通过unsafe标记后,该函数或者该代码块区域,内存管理由我们开发人员自己掌控(内存资源的分配和释放),在C#中,GC不管理该区域的内存.

  先看看使用指针的代码

  unsafe

  {

  byte* pIn=(byte*)srcData.Scan0.ToPointer();

  byte* pOut=(byte*)dstData.Scan0.ToPointer();

  int stride=srcData.Stride;

  byte* p;

  //省略

  //XXX

  }

  Scan0是个句柄(Intptr),通过ToPointer返回一个void *指针,再转换为byte*指针.

  来看看ToPointer函数内部

  [SecurityCritical]

  private unsafe void* m_value;

  [SecuritySafeCritical]

  [CLSCompliant(false)]

  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]

  [NonVersionable]

  public unsafe void* ToPointer() //调用ToPointer返回void类型的指针

  {

  return m_value;

  }阅读IntPtr源码

  看看完整IntPtr句柄源码,去除一些游戏账号购买特性标签

  [Serializable]

  public struct IntPtr : ISerializable

  {

  [System.Security.SecurityCritical]

  unsafe private void* m_value; // The compiler treats void* closest to uint hence explicit casts are required to preserve int behavior

  public static readonly IntPtr Zero;

  // fast way to compare IntPtr to (IntPtr)0 while IntPtr.Zero doesn't work due to slow statics access

  internal unsafe bool IsNull()

  {

  return (this.m_value==null);

  }

  public unsafe IntPtr(int value)

  {

  #if WIN32

  m_value=(void*)value;

  #else

  m_value=(void*)(long)value;

  #endif

  }

  public unsafe IntPtr(long value)

  {

  #if WIN32

  m_value=(void*)checked((int)value);

  #else

  m_value=(void*)value;

  #endif

  }

  public unsafe IntPtr(void* value)

  {

  m_value=value;

  }

  private unsafe IntPtr(SerializationInfo info, StreamingContext context)

  {

  long l=info.GetInt64("value");

  if (Size==4 && (l > Int32.MaxValue || l

  {

  throw new ArgumentException(Environment.GetResourceString("Serialization_InvalidPtrValue"));

  }

  m_value=(void*)l;

  }

  public unsafe override bool Equals(Object obj)

  {

  if (obj is IntPtr)

  {

  return (m_value==((IntPtr)obj).m_value);

  }

  return false;

  }

  public unsafe override int GetHashCode()

  {

  return unchecked((int)((long)m_value));

  }

  public unsafe int ToInt32()

  {

  #if WIN32

  return (int)m_value;

  #else

  long l=(long)m_value;

  return checked((int)l);

  #endif

  }

  public unsafe long ToInt64()

  {

  #if WIN32

  return (long)(int)m_value;

  #else

  return (long)m_value;

  #endif

  }

  public unsafe override String ToString()

  {

  #if WIN32

  return ((int)m_value).ToString(CultureInfo.InvariantCulture);

  #else

  return ((long)m_value).ToString(CultureInfo.InvariantCulture);

  #endif

  }

  public unsafe String ToString(String format)

  {

  #if WIN32

  return ((int)m_value).ToString(format, CultureInfo.InvariantCulture);

  #else

  return ((long)m_value).ToString(format, CultureInfo.InvariantCulture);

  #endif

  }

  public static explicit operator IntPtr(int value)

  {

  return new IntPtr(value);

  }

  public static explicit operator IntPtr(long value)

  {

  return new IntPtr(value);

  }

  public static unsafe explicit operator IntPtr(void* value)

  {

  return new IntPtr(value);

  }

  public static unsafe explicit operator void*(IntPtr value)

  {

  return value.m_value;

  }

  public unsafe static explicit operator int(IntPtr value)

  {

  #if WIN32

  return (int)value.m_value;

  #else

  long l=(long)value.m_value;

  return checked((int)l);

  #endif

  }

  public unsafe static explicit operator long(IntPtr value)

  {

  #if WIN32

  return (long)(int)value.m_value;

  #else

  return (long)value.m_value;

  #endif

  }

  public unsafe static bool operator==(IntPtr value1, IntPtr value2)

  {

  return value1.m_value==value2.m_value;

  }

  public unsafe static bool operator !=(IntPtr value1, IntPtr value2)

  {

  return value1.m_value !=value2.m_value;

  }

  public static IntPtr Add(IntPtr pointer, int offset)

  {

  return pointer + offset;

  }

  public static IntPtr operator +(IntPtr pointer, int offset)

  {

  #if WIN32

  return new IntPtr(pointer.ToInt32() + offset);

  #else

  return new IntPtr(pointer.ToInt64() + offset);

  #endif

  }

  public static IntPtr Subtract(IntPtr pointer, int offset)

  {

  return pointer - offset;

  }

  public static IntPtr operator -(IntPtr pointer, int offset)

  {

  #if WIN32

  return new IntPtr(pointer.ToInt32() - offset);

  #else

  return new IntPtr(pointer.ToInt64() - offset);

  #endif

  }

  public static int Size

  {

  get

  {

  #if WIN32

  return 4;

  #else

  return 8;

  #endif

  }

  }

  public unsafe void* ToPointer()

  {

  return m_value;

  }

  }