c# - IntPtr 和 UIntPtr 的区别

标签 c# .net pointers intptr

我正在查看 RegOpenKeyEx 的 P/Invoke 声明当我注意到页面上的这条评论时:

Changed IntPtr to UIntPtr: When invoking with IntPtr 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.

这对我来说没有多大意义:IntPtrUIntPtr 都应该表示指针,所以它们的大小应该与操作系统的位数相匹配——要么是 32 位或 64 位。由于这些不是数字而是指针,因此它们的带符号数值无关紧要,重要的是代表它们指向的地址的位。我想不出这两者之间会有差异的任何原因,但这条评论让我不确定。

是否有使用 UIntPtr 而不是 IntPtr 的特定原因?根据documentation :

The IntPtr type is CLS-compliant, while the UIntPtr type is not. Only the IntPtr type is used in the common language runtime. The UIntPtr type is provided mostly to maintain architectural symmetry with the IntPtr type.

当然,这意味着没有区别(只要有人不尝试将值转换为整数)。那么pinvoke.net的上述评论是不是不正确?

编辑:

看完MarkH's answer ,我做了一些检查,发现 .NET 应用程序不支持大地址,并且在以 32 位模式编译时只能处理 2GB 的虚拟地址空间。 (可以使用 hack 来打开大地址感知标志,但 MarkH 的回答表明,.NET Framework 内部的检查会破坏一些东西,因为地址空间被假定为只有 2GB,而不是 3GB。)

这意味着指针可以拥有的所有正确虚拟内存地址(就 .NET Framework 而言)将介于 0x00000000 和 0x7FFFFFFF 之间。当此范围转换为带符号的 int 时,没有任何值是负数,因为最高位未设置。这强化了我的信念,即使用 IntPtr 与 UIntPtr 没有区别。我的推理是否正确?

Fermat2357 指出上面的编辑是错误的。

最佳答案

UIntPtrIntPtr 在内部实现为

private unsafe void* m_value;

你们都是对的,只是管理代表地址的位。

我唯一能想到的溢出问题是,如果您尝试执行指针算术。这两个类都支持添加和减去偏移量。但同样在这种情况下,二进制表示在这样的操作之后应该没问题。

根据我的经验,我也更喜欢 UIntPtr,因为我认为指针是无符号对象。但这无关紧要,只是我的意见。

如果您在您的案例中使用 IntPtrUIntPtr 似乎没有任何区别。

编辑:

IntPtr 符合 CLS,因为 CLR 之上的语言不支持无符号。

关于c# - IntPtr 和 UIntPtr 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13170801/

相关文章:

c++ - 从函数返回指向局部变量的静态指针

c# - 如何获得更好的读取文件的方法?

c# - 如何映射组件集合(值对象)

c# - LINQ 选择实体并将其转换为 ViewModel

c# - 更好的做法 : CheckBox DataBindings vs CheckedChanged event

C# - 将对象转换为画笔 (WPF)

c++ - 检查 NULL 值 C++ 的引用

c# - PInvoke - 从指针编码结构数组

c# - 隐藏轴,同时仍然能够缩放和平移

c# - 按顺序合并两个或多个列表