我正在查看 RegOpenKeyEx
的 P/Invoke 声明当我注意到页面上的这条评论时:
Changed
IntPtr
toUIntPtr
: When invoking withIntPtr
for the handles, you will run into an Overflow.UIntPtr
is the right choice if you wish this to work correctly on 32 and 64 bit platforms.
这对我来说没有多大意义:IntPtr
和 UIntPtr
都应该表示指针,所以它们的大小应该与操作系统的位数相匹配——要么是 32 位或 64 位。由于这些不是数字而是指针,因此它们的带符号数值无关紧要,重要的是代表它们指向的地址的位。我想不出这两者之间会有差异的任何原因,但这条评论让我不确定。
是否有使用 UIntPtr
而不是 IntPtr
的特定原因?根据documentation :
The
IntPtr
type is CLS-compliant, while theUIntPtr
type is not. Only theIntPtr
type is used in the common language runtime. TheUIntPtr
type is provided mostly to maintain architectural symmetry with theIntPtr
type.
当然,这意味着没有区别(只要有人不尝试将值转换为整数)。那么pinvoke.net的上述评论是不是不正确?
编辑:
看完MarkH's answer ,我做了一些检查,发现 .NET 应用程序不支持大地址,并且在以 32 位模式编译时只能处理 2GB 的虚拟地址空间。 (可以使用 hack 来打开大地址感知标志,但 MarkH 的回答表明,.NET Framework 内部的检查会破坏一些东西,因为地址空间被假定为只有 2GB,而不是 3GB。)
这意味着指针可以拥有的所有正确虚拟内存地址(就 .NET Framework 而言)将介于 0x00000000 和 0x7FFFFFFF 之间。当此范围转换为带符号的 int
时,没有任何值是负数,因为最高位未设置。这强化了我的信念,即使用 IntPtr 与 UIntPtr 没有区别。我的推理是否正确?
Fermat2357 指出上面的编辑是错误的。
最佳答案
UIntPtr
和 IntPtr
在内部实现为
private unsafe void* m_value;
你们都是对的,只是管理代表地址的位。
我唯一能想到的溢出问题是,如果您尝试执行指针算术。这两个类都支持添加和减去偏移量。但同样在这种情况下,二进制表示在这样的操作之后应该没问题。
根据我的经验,我也更喜欢 UIntPtr
,因为我认为指针是无符号对象。但这无关紧要,只是我的意见。
如果您在您的案例中使用 IntPtr
或 UIntPtr
似乎没有任何区别。
编辑:
IntPtr
符合 CLS,因为 CLR 之上的语言不支持无符号。
关于c# - IntPtr 和 UIntPtr 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13170801/