IntPtr和UIntPtr之间的区别

xxb*_*bcc 11 .net c# pointers intptr

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

更改IntPtrUIntPtr:使用IntPtr句柄调用时,您将遇到溢出.UIntPtr如果您希望在32位和64位平台上正常工作,则是正确的选择.

这并没有太大的意义对我说:都IntPtrUIntPtr应该代表指针因此其大小应与OS的位数-无论是32位或64位.由于这些不是数字而是指针,因此它们的带符号数值应该无关紧要,只有表示它们指向的地址的位.我想不出为什么这两者之间会有什么不同,但是这个评论让我不确定.

是否有使用的具体原因UIntPtr而不是IntPtr?根据文件:

IntPtr类型是符合CLS,而UIntPtr类型不是.IntPtr在公共语言运行库中仅使用该类型.UIntPtr提供的类型主要是为了保持与IntPtr类型的架构对称性.

当然,这意味着没有区别(只要有人不尝试将值转换为整数).所以pinvoke.net的上述评论是错误的吗?

编辑:

在阅读了MarkH的回答之后,我做了一些检查,发现.NET应用程序不是大地址识别,并且在32位模式下编译时只能处理2GB的虚拟地址空间.(可以使用hack打开大地址识别标志,但MarkH的答案显示.NET Framework内的检查会破坏因为地址空间仅为2GB,而不是3GB.)

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

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

Dav*_*itz 9

UIntPtr并且IntPtr内部实现为

private unsafe void* m_value;
Run Code Online (Sandbox Code Playgroud)

你是对的,只是管理代表地址的位.

我唯一可以考虑溢出问题的是你尝试执行指针算术.这两个类都支持添加和减去偏移量.但是在这种情况下,二进制表示在这样的操作之后应该是正常的.

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

如果您使用IntPtrUIntPtr在您的情况下似乎没有任何区别.

编辑:

IntPtr 是CLS兼容的,因为CLR之上的语言不支持unsigned.

  • 我发现微软做的这种框架设计非常令人不安 - 为了对称而有一个重复无意义的类型来包装指针.他们应该只创建一个包装器并将其命名为SafePtr,而不是进入签名/未签名的区域,这根本没有意义. (6认同)