ASCII码 ASCII码

C#到底有没有指针

发布于:2021-12-14 11:25:12  栏目:技术文档

  起因

  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 < Int32.MinValue))

  {

  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;

  }

  }

相关推荐
阅读 +