C# 将偏移量添加到IntPtr
我正在寻找一种特别是在C#或.NET中执行指针操作的方法 我想做一些非常简单的事情 有一个指针IntPtr,我想得到指向前面2个字节的IntPtr对象 我读了一些帖子,说这个愚蠢的片段会有用C# 将偏移量添加到IntPtr,c#,.net,pinvoke,interop,C#,.net,Pinvoke,Interop,我正在寻找一种特别是在C#或.NET中执行指针操作的方法 我想做一些非常简单的事情 有一个指针IntPtr,我想得到指向前面2个字节的IntPtr对象 我读了一些帖子,说这个愚蠢的片段会有用 IntPtr ptr = new IntPtr(oldptr.ToInt32() + 2); 但我怀疑这句话是否也适用于64位机器(因为寻址是64位的) 我发现这个优雅的方法可以添加偏移量,但不幸的是,它只在.NET 4.0中使用我建议您使用ToInt64()和long来执行计算。通过这种方式,您将避免在
IntPtr ptr = new IntPtr(oldptr.ToInt32() + 2);
但我怀疑这句话是否也适用于64位机器(因为寻址是64位的)
我发现这个优雅的方法可以添加偏移量,但不幸的是,它只在.NET 4.0中使用我建议您使用ToInt64()和long来执行计算。通过这种方式,您将避免在64位版本的.NET framework上出现问题
IntPtr ptr = new IntPtr(oldptr.ToInt64() + 2);
这会在32位系统上增加一点开销,但更安全。您可以使用扩展方法:
public static IntPtrExtensions {
public static IntPtr Add( this IntPtr ptr, int offSet ) {
IntPtr ret = new IntPtr( ptr.ToInt64() + offSet );
return ret;
}
}
// ... somewhere else ...
IntPtr pointer = GetHandle().Add( 15 );
对于C#中的指针算法,您应该在
不安全的上下文中使用适当的指针:
class PointerArithmetic
{
unsafe static void Main()
{
int* memory = stackalloc int[30];
long* difference;
int* p1 = &memory[4];
int* p2 = &memory[10];
difference = (long*)(p2 - p1);
System.Console.WriteLine("The difference is: {0}", (long)difference);
}
}
IntPtr
类型用于传递句柄或指针,也用于编组到支持指针的语言。但它不适用于指针算术。我发现我可以通过使用Marshal.ReadByte()、Marshal.ReadInt16()等方法避免指针操作。这组方法允许指定与IntPtr相关的偏移量…在.net 4中添加了静态Add()和Subtract()方法
IntPtr ptr = IntPtr.Add(oldPtr, 2);
公共静态类intptrex
{
#区域方法:算术
公共静态IntPtr递减(此IntPtr指针,Int32值)
{
返回增量(指针,-值);
}
公共静态IntPtr递减(此IntPtr指针,Int64值)
{
返回增量(指针,-值);
}
公共静态IntPtr递减(此IntPtr指针,IntPtr值)
{
交换机(IntPtr.Size)
{
案例大小(Int32):
返回(新的IntPtr(指针.ToInt32()-value.ToInt32());
违约:
返回(新的IntPtr(指针.ToInt64()-value.ToInt64());
}
}
公共静态IntPtr增量(此IntPtr指针,Int32值)
{
未经检查
{
交换机(IntPtr.Size)
{
案例大小(Int32):
返回(新的IntPtr(指针.ToInt32()+值));
违约:
返回(新的IntPtr(指针.ToInt64()+值));
}
}
}
公共静态IntPtr增量(此IntPtr指针,Int64值)
{
未经检查
{
交换机(IntPtr.Size)
{
案例大小(Int32):
返回(新的IntPtr((Int32)(pointer.ToInt32()+值));
违约:
返回(新的IntPtr(指针.ToInt64()+值));
}
}
}
公共静态IntPtr增量(此IntPtr指针,IntPtr值)
{
未经检查
{
交换机(IntPtr.Size)
{
案例大小(整数):
返回新的IntPtr(指针.ToInt32()+值.ToInt32());
违约:
返回新的IntPtr(指针.ToInt64()+值.ToInt64());
}
}
}
#端区
#区域方法:比较
公共静态Int32比较(此IntPtr左,Int32右)
{
返回左。比较((UInt32)右);
}
公共静态Int32比较(此IntPtr左,IntPtr右)
{
if(left.ToUInt64()>right.ToUInt64())
返回1;
if(left.ToUInt64()right)
返回1;
if(left.ToUInt64()=0);
}
公共静态布尔LessThanOrEqualTo(此IntPtr左,IntPtr右)
{
返回(左。比较到(右)在64位计算机上,一个字节仍然是一个字节。因此,它仍然会向前跳过两个字节。@dan:是的,但字节的地址可能超出32位范围!Marcin认为这对于64位无效是正确的。+1表示实指针算术,而不是滥用整数ALU来执行地址计算。现在Microsoft in.NET 4具有introduced IntPtr.Add返回“一个新指针,它反映了指针的偏移量的增加”,这使得IntPtr对于指针运算非常方便,并且似乎表明Microsoft希望使用它。使用不安全代码存在限制-因此在编译过程中需要/unsafe标志。如果可能,最好避免使用/unsafe标志。还值得注意的是,ALU用于计算地址,无论使用何种方法你使用。我看不出它是如何通过手工计算被“滥用”的。不管这是什么样的静态。对不起,我刚刚通过对这个答案进行投票,破坏了你的满分1000分;/这怎么不是最好的答案……也许加上一些注释,但代码说明了这一点
public static class IntPtrExtensions
{
#region Methods: Arithmetics
public static IntPtr Decrement(this IntPtr pointer, Int32 value)
{
return Increment(pointer, -value);
}
public static IntPtr Decrement(this IntPtr pointer, Int64 value)
{
return Increment(pointer, -value);
}
public static IntPtr Decrement(this IntPtr pointer, IntPtr value)
{
switch (IntPtr.Size)
{
case sizeof(Int32):
return (new IntPtr(pointer.ToInt32() - value.ToInt32()));
default:
return (new IntPtr(pointer.ToInt64() - value.ToInt64()));
}
}
public static IntPtr Increment(this IntPtr pointer, Int32 value)
{
unchecked
{
switch (IntPtr.Size)
{
case sizeof(Int32):
return (new IntPtr(pointer.ToInt32() + value));
default:
return (new IntPtr(pointer.ToInt64() + value));
}
}
}
public static IntPtr Increment(this IntPtr pointer, Int64 value)
{
unchecked
{
switch (IntPtr.Size)
{
case sizeof(Int32):
return (new IntPtr((Int32)(pointer.ToInt32() + value)));
default:
return (new IntPtr(pointer.ToInt64() + value));
}
}
}
public static IntPtr Increment(this IntPtr pointer, IntPtr value)
{
unchecked
{
switch (IntPtr.Size)
{
case sizeof(int):
return new IntPtr(pointer.ToInt32() + value.ToInt32());
default:
return new IntPtr(pointer.ToInt64() + value.ToInt64());
}
}
}
#endregion
#region Methods: Comparison
public static Int32 CompareTo(this IntPtr left, Int32 right)
{
return left.CompareTo((UInt32)right);
}
public static Int32 CompareTo(this IntPtr left, IntPtr right)
{
if (left.ToUInt64() > right.ToUInt64())
return 1;
if (left.ToUInt64() < right.ToUInt64())
return -1;
return 0;
}
public static Int32 CompareTo(this IntPtr left, UInt32 right)
{
if (left.ToUInt64() > right)
return 1;
if (left.ToUInt64() < right)
return -1;
return 0;
}
#endregion
#region Methods: Conversion
public unsafe static UInt32 ToUInt32(this IntPtr pointer)
{
return (UInt32)((void*)pointer);
}
public unsafe static UInt64 ToUInt64(this IntPtr pointer)
{
return (UInt64)((void*)pointer);
}
#endregion
#region Methods: Equality
public static Boolean Equals(this IntPtr pointer, Int32 value)
{
return (pointer.ToInt32() == value);
}
public static Boolean Equals(this IntPtr pointer, Int64 value)
{
return (pointer.ToInt64() == value);
}
public static Boolean Equals(this IntPtr left, IntPtr ptr2)
{
return (left == ptr2);
}
public static Boolean Equals(this IntPtr pointer, UInt32 value)
{
return (pointer.ToUInt32() == value);
}
public static Boolean Equals(this IntPtr pointer, UInt64 value)
{
return (pointer.ToUInt64() == value);
}
public static Boolean GreaterThanOrEqualTo(this IntPtr left, IntPtr right)
{
return (left.CompareTo(right) >= 0);
}
public static Boolean LessThanOrEqualTo(this IntPtr left, IntPtr right)
{
return (left.CompareTo(right) <= 0);
}
#endregion
#region Methods: Logic
public static IntPtr And(this IntPtr pointer, IntPtr value)
{
switch (IntPtr.Size)
{
case sizeof(Int32):
return (new IntPtr(pointer.ToInt32() & value.ToInt32()));
default:
return (new IntPtr(pointer.ToInt64() & value.ToInt64()));
}
}
public static IntPtr Not(this IntPtr pointer)
{
switch (IntPtr.Size)
{
case sizeof(Int32):
return (new IntPtr(~pointer.ToInt32()));
default:
return (new IntPtr(~pointer.ToInt64()));
}
}
public static IntPtr Or(this IntPtr pointer, IntPtr value)
{
switch (IntPtr.Size)
{
case sizeof(Int32):
return (new IntPtr(pointer.ToInt32() | value.ToInt32()));
default:
return (new IntPtr(pointer.ToInt64() | value.ToInt64()));
}
}
public static IntPtr Xor(this IntPtr pointer, IntPtr value)
{
switch (IntPtr.Size)
{
case sizeof(Int32):
return (new IntPtr(pointer.ToInt32() ^ value.ToInt32()));
default:
return (new IntPtr(pointer.ToInt64() ^ value.ToInt64()));
}
}
#endregion
}