向 IntPtr 添加偏移量
Posted
技术标签:
【中文标题】向 IntPtr 添加偏移量【英文标题】:Add offset to IntPtr 【发布时间】:2009-12-08 11:02:11 【问题描述】:我正在寻找一种特别是在 C# 或 .NET 中执行指针操作的方法。
我想做一些非常简单的事情
有一个指针 IntPtr 我想获得指向前面 2 个字节的 IntPtr 对象。
我读过一些帖子说愚蠢的 sn-p 会起作用......
IntPtr ptr = new IntPtr(oldptr.ToInt32() + 2);
但我怀疑这条语句是否也适用于 64 位机器(因为那里的寻址是 64 位的)..
我发现了这种添加偏移量的优雅方法,但不幸的是仅在 .NET 4.0 中 http://msdn.microsoft.com/en-us/library/system.intptr.add%28VS.100%29.aspx
【问题讨论】:
一个字节在 64 位机器上仍然是一个字节。所以,它仍然会向前跳过两个字节。 @dan:是的,但是字节的地址可以在 32 位范围之外! Marcin 是正确的,这对 64 位无效。 【参考方案1】:在 .net 中添加了 4 个静态 Add() 和 Subtract() 方法。
IntPtr ptr = IntPtr.Add(oldPtr, 2);
http://msdn.microsoft.com/en-us/library/system.intptr.add.aspx
【讨论】:
为什么这是静态的。抱歉,我刚刚破坏了你的 1000 分的满分,为这个答案投了赞成票;/【参考方案2】:我建议您使用 ToInt64() 和 long 来执行您的计算。这样可以避免 .NET 框架的 64 位版本出现问题。
IntPtr ptr = new IntPtr(oldptr.ToInt64() + 2);
这在 32 位系统上增加了一点开销,但更安全。
【讨论】:
【参考方案3】:对于 C# 中的指针运算,您应该在 unsafe
上下文中使用正确的指针:
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
类型用于传递句柄或指针,也用于编组到支持指针的语言。但它不适用于指针运算。
【讨论】:
+1 用于实指针运算,而不是滥用整数 ALU 来执行地址计算。 现在微软在 .NET 4 中引入了 IntPtr.Add ,它返回“一个新的指针,它反映了对指针的偏移量的添加”,这使得 IntPtr 便于指针算术,并且似乎表明微软期望它被用于那个。 使用不安全代码是有限制的——因此在编译期间需要 /unsafe 标志。如果可能的话,最好避免它。另外值得注意的是,无论您使用哪种方法,ALU 都用于计算地址。我看不出它是如何通过手动计算被“滥用”的。【参考方案4】:我发现我可以通过使用 Marshal.ReadByte()、Marshal.ReadInt16() 等方法来避免指针操作。这组方法允许指定与 IntPtr 相关的偏移量...
【讨论】:
【参考方案5】: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
【讨论】:
这不是最佳答案...也许添加一些评论,但代码不言自明...【参考方案6】:您可以使用扩展方法:
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 );
【讨论】:
以上是关于向 IntPtr 添加偏移量的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 向视图添加 -y 偏移量,但将视图拉伸到底部
pandas使用pd.DateOffset生成时间偏移量(指定年数月数天数小时分钟)把dataframe数据中的时间数据列统一偏移(相加偏移向后移动时间时间增加)
pandas使用pd.DateOffset生成时间偏移量(指定年数月数天数小时分钟)把dataframe数据中的时间数据列统一偏移(相加偏移向后移动时间时间增加)
pandas使用pd.DateOffset生成时间偏移量把dataframe数据中的时间数据列统一相加N天放大向后偏移N天