Golang中的* uint和uintptr有什么区别?

Ale*_*sen 2 pointers go

根据Golang导览,我们提供了以下整数类型:

int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr
Run Code Online (Sandbox Code Playgroud)

从理论上讲,这意味着我们还可以如下指向所有这些类型的指针:

*int  *int8  *int16  *int32  *int64
*uint *uint8 *uint16 *uint32 *uint64 *uintptr
Run Code Online (Sandbox Code Playgroud)

如果是这种情况,那么我们已经有一个指向* uint形式的uint的指针。这会使uintptr变得多余。在官方文档不会在此洒下多少光:

uintptr is an integer type that is large enough to hold the bit pattern of any pointer.
Run Code Online (Sandbox Code Playgroud)

据我了解,这意味着uint的位宽是在编译时根据目标体系结构(通常为32位或64位)确定的。指针宽度也应缩放到目标体系结构似乎是合乎逻辑的(IE:32位* uint指向32位uint)。Golang就是这种情况吗?

另一个想法是,也许在添加uintptr时使语法在进行多个间接寻址时(IE:foo *uinptrvs foo **uint)不太混乱?

我最后的想法是,指针和整数在Golang中可能是不兼容的数据类型。这将非常令人沮丧,因为硬件本身在它们之间没有任何区别。例如,“分支到该地址”指令可以使用来自同一寄存器的与“添加此值”指令中相同的数据。

uintptr的真正意义(双关语)是什么?

tor*_*rek 7

简短的答案是“永不使用uintptr”。

长答案是uintptr在那里绕过类型系统,并允许Go实现者在Go中编写包括垃圾收集系统在内的Go运行时库,并使用未 C指针处理 C指针来调用C调用代码,包括系统调用去吧

如果您充当实施者(例如,提供对新OS上的系统调用的访问权限),则需要uintptr。您还需要了解使用它所需的所有特殊技巧,例如,如果操作系统要对操作系统级别的线程进行堆栈操作,则将goroutine锁定到操作系统级别的线程。(如果将其与Go指针一起使用,则可能还需要告诉编译器不要移动goroutine堆栈,这是通过特殊的编译时指令完成的。)

编辑:正如kostix在注释中指出的那样,运行时系统将a unsafe.Pointer视为对对象的引用,从而使该对象对于GC保持活动状态。它认为是uintptr这样的参考。(也就是说,虽然unsafe.Pointer具有指针类型,但uintptr具有整数类型。)另请参见package文档unsafe

  • 为了使这个好答案变得不那么神奇……– uintptr可能包含任何指针值,但是与unsafe.Pointer相反,GC不会将uintptr视为对其所指向的内存块的实时引用。这就是为什么除非在某些狭窄的受控情况下,否则无法使用它们。 (2认同)

Not*_*fer 5

uintptr 只是内存地址的整数表示形式,无论它指向的实际类型是什么。有点像void *C 语言,或者只是将指针转换为整数。它的目的是用于不安全的黑魔法,并且不会在日常的 go 代码中使用。