究竟什么是IntPtr?

Cal*_*ers 163 c# intptr

通过使用IntelliSense并查看其他人的代码,我遇到过这种IntPtr类型; 每次需要使用时,我只需要放置nullIntPtr.Zero发现大多数功能都可以使用.究竟是什么以及何时/为何使用它?

Sam*_*ell 154

它是"本机(特定于平台)的大小整数." 它在内部表示为void*暴露为整数.只要您需要存储非托管指针并且不想使用unsafe代码,就可以使用它.IntPtr.Zero是有效的NULL(空指针).

  • 通常(跨编程语言),指针是表示内存中物理位置的数字.A*null*指针(几乎总是)指向0,并且被广泛认为是"不指向任何东西".由于系统具有不同数量的受支持内存,因此保持该数字并不总是需要相同数量的字节,因此我们称之为"本机大小整数",可以在任何特定系统上保存指针. (90认同)
  • 指针指向内存中的地址.在托管语言中,您有引用(地址可以移动),而在非托管语言中,您有指针(地址是固定的) (50认同)
  • 它被称为IntPtr,因为要从非托管本机代码C/C++中使用它,您将不得不使用类比类型:intptr_t.C#的IntPtr完全映射到C/C++的intptr_t.它可能实现为intptr_t.在C/C++中,intptr_t类型保证与void*type的大小相同. (8认同)
  • @ 280Z28评论的+1,这是我见过的最简洁的指针解释. (5认同)
  • 或者只是“ OpaqueHandle” (2认同)
  • @Trap"特定于平台的类型,用于表示指针或句柄." 不是"特定于平台的整数","表示指针或句柄的特定于平台的方式".`IntPtr`非常有意义,因为它是一个整数(如数学整数)和指针(如指针).`Int`部分与int类型没什么关系 - 它是一个概念,而不是一个特定的类型.虽然公平,但CLI规范中唯一指出的是它确实是"整数,原生大小".那好吧 :) (2认同)

Dan*_*ker 65

它是一个足够大的值类型,用于存储本机或不安全代码中使用的内存地址,但不能直接用作安全托管代码中的内存地址.

您可以使用IntPtr.Size以确定您是在32位还是64位进程中运行,因为它将分别为4或8个字节.

  • 关于检测进程的地址空间大小的好处. (15认同)

buf*_*erz 43

这是一个例子:

我正在编写一个与高速摄像头连接的C#程序.相机有自己的驱动程序,可以自动获取图像并将它们加载到计算机的内存中.

因此,当我准备将最新的图像带入我的程序中时,相机驱动程序为我提供了一个IntPtr,以便将图像存储在物理内存中,因此我不必浪费时间/资源来创建另一个用于存储已经存储在内存中的图像的内存块.IntPtr只显示图像已经存在的位置.

  • 因此IntPtr simple允许您在托管代码中使用非托管指针(如相机驱动程序中使用的那样)? (5认同)
  • 是.在这种情况下,很可能相机驱动程序使用非托管驱动程序,但为了在Managed-only世界中正常运行,它提供了IntPtr以允许我安全地处理数据. (3认同)
  • 那么,为什么不只给您一个流(字节数组)呢?为什么不安全或无法返回值? (2认同)

nob*_*bar 34

直接解释

一个IntPtr的是一个整数,其是大小相同的指针.

您可以使用IntPtr将指针值存储在非指针类型中.此功能在.NET中很重要,因为使用指针非常容易出错,因此在大多数情况下都是非法的.通过允许指针值存储在"安全"数据类型中,不安全代码段之间的管道可以用更安全的高级代码实现 - 甚至可以用不直接支持指针的.NET语言实现.

IntPtr的大小是特定于平台的,但这个细节很少需要考虑,因为系统会自动使用正确的大小.

"IntPtr"这个名字令人困惑 - 这Handle可能更合适.我最初的猜测是,"IntPtr的"是一个指针一个整数.IntPtrMSDN文档进入了一些有些神秘的细节,而没有提供有关名称含义的深入见解.

另一种观点

An IntPtr是一个有两个限制的指针:

  1. 它不能直接解除引用
  2. 它不知道它指向的数据类型.

换句话说,a IntPtr就像void*- 但是具有额外的功能,它可以(但不应该)用于基本指针算术.

为了取消引用IntPtr,你可以将它转换为真正的指针(只能在"不安全"的上下文中执行的操作),或者你可以将它传递给辅助程序,例如InteropServices.Marshal类提供的程序.使用Marshal该类会产生安全错觉,因为它不需要您处于明确的"不安全"环境中.但是,它不会消除使用指针时固有的崩溃风险.

  • "C"编程语言的C99标准中有一个名称为"intptr"的先例.http://linux.die.net/man/3/intptr_t. (2认同)
  • 请参阅http://www.cplusplus.com/reference/cstdint上的"intptr_t". (2认同)

Kni*_*ins 13

什么是指针?

在所有语言中,指针是一种存储内存地址的变量,您可以要求它们告诉您它们指向的地址或它们指向的地址.

指针可以被认为是一种书签.除了用于快速跳转到书中的页面之外,指针用于跟踪或映射内存块.

想象一下你的程序的内存就像一个65535字节的大数组.

指针乖乖地指着

指针每个记住一个存储器地址,因此它们每个指向存储器中的单个地址.

作为一个群体,指针记住并记住内存地址,遵守你的每一个命令和恶心.

你是他们的国王.

C#中的指针

特别是在C#中,指针是一个整数变量,存储0到65534之间的内存地址.

同样特定于C#,指针的类型为int,因此也是有符号的.

但是,您不能使用带负数的地址,也不能访问65534以上的地址.任何尝试这样做都会抛出System.AccessViolationException.

一个名为MyPointer的指针声明如下:

int*MyPointer;

C#中的指针是一个int,但C#中的内存地址从0开始,一直延伸到65534.

尖锐的东西应该特别小心处理

"不安全"这个词为了吓唬你,原因很简单:指针是尖尖的东西,尖头的东西,如剑,斧头,指针等应该特别小心处理.

指针为程序员提供了对系统的严格控制.因此,错误可能会产生更严重的后果.

为了使用指针,必须在程序的属性中启用不安全的代码,并且指针必须专门用于标记为不安全的方法或块.

不安全块的示例

unsafe
{
    // Place code carefully and responsibly here.

}
Run Code Online (Sandbox Code Playgroud)

如何使用指针

声明或实例化变量或对象时,它们存储在内存中.

  • 使用*符号前缀声明指针.

int *MyPointer;

  • 要获取变量的地址,请使用&符号前缀.

MyPointer = &MyVariable;

将地址分配给指针后,以下情况适用:

  • 没有*前缀来指向被指向为int的内存地址.

MyPointer = &MyVariable; // Set MyPointer to point at MyVariable

  • 使用*前缀来获取存储在指向的内存地址的值.

"MyPointer is pointing at " + *MyPointer;

由于指针是保存存储器地址的变量,因此该存储器地址可以存储在指针变量中.

仔细和负责任地使用指针的示例

    public unsafe void PointerTest()
    {
        int x = 100; // Create a variable named x

        int *MyPointer = &x; // Store the address of variable named x into the pointer named MyPointer

        textBox1.Text = ((int)MyPointer).ToString(); // Displays the memory address stored in pointer named MyPointer

        textBox2.Text = (*MyPointer).ToString(); // Displays the value of the variable named x via the pointer named MyPointer.

    }
Run Code Online (Sandbox Code Playgroud)

请注意,指针的类型是int.这是因为C#将内存地址解释为整数(int).

为什么它是int而不是uint?

没有充分的理由.

为什么要使用指针?

指针很有趣.由于大部分计算机都由内存控制,指针使程序员能够更好地控制程序的内存.

内存监控.

使用指针读取内存块并监视指向的值如何随时间变化.

负责任地更改这些值并跟踪更改对计算机的影响.

  • `65534`作为指针范围似乎非常错误.你应该提供一个参考. (2认同)
  • 我投了赞成票,因为这是一篇很好的文章,解释了指针。我希望看到对您提到的规范的一些参考(如上所述)。然而; 这个答案与问题无关。问题是关于```System.IntPtr```。我希望看到最后更新的答案解释什么也是 ```System.IntPtr``` 以及它如何与 C# 中的不安全指针相关。 (2认同)

Zyp*_*rax 7

MSDN告诉我们:

IntPtr类型设计为整数,其大小是特定于平台的.也就是说,这种类型的实例预计在32位硬件和操作系统上为32位,在64位硬件和操作系统上为64位.

IntPtr类型可以由支持指针的语言使用,并且作为在支持指针和不支持指针的语言之间引用数据的常用方法.

IntPtr对象也可用于保存句柄.例如,IntPtr的实例广泛用于System.IO.FileStream类中以保存文件句柄.

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

http://msdn.microsoft.com/en-us/library/system.intptr(VS.71).aspx


Chr*_*isF 5

嗯,这是MSDN页面与交易IntPtr.

第一行是:

特定于平台的类型,用于表示指针或句柄.

至于页面继续指示什么是指针或句柄:

IntPtr类型可以由支持指针的语言使用,并且作为在支持指针和不支持指针的语言之间引用数据的常用方法.

IntPtr对象也可用于保存句柄.例如,IntPtr的实例广泛用于System.IO.FileStream类中以保存文件句柄.

指针是对存储区域的引用,该区域包含您感兴趣的一些数据.

句柄可以是对象的标识符,并且在双方都需要访问该对象时在方法/类之间传递.