首页 > 解决方案 > 为什么 unsafe.Sizeof 返回一个 uintptr?

问题描述

根据文档(https://golang.org/pkg/unsafe/#Sizeofunsafe.Sizeof返回给定表达式的大小(以字节为单位)。理想情况下,任何给定表达式的大小都可以用 auint32或表示uint64。那为什么 Golang 会返回 auintptr呢?这不是很混乱吗?Auintptr应该保存一个指向某个数据值的指针,但在这种情况下,它实际上不是一个指针,它只是一个数字,对吧?

标签: go

解决方案


评论中有很多很好的答案,归结为“因为它足够大,但又不太大”。不过,我认为从历史的角度来看这可能会有所帮助,特别注意这一切是如何在 C 编程语言中发生的。

在非常古老的(准标准)C 中,如果你能追溯到足够远的时间,甚至没有明确的unsigned整数类型。PDP-11 具有:

  • char, 8 位,有符号;
  • int, 16 位,有符号;和
  • 指针,16 位,无符号。

那是:

int i;
int *u;

是你如何制作两个整数,i有符号和u无符号。设置i为 32767 (0x7fff) 然后增加它给你 -32768 (0x8000),它逐渐增加到 -1 (0xffff) 然后为零。设置u为 32767,然后增加它给你 32768,它逐渐增加到 65535,然后翻转到零。

整数和指针之间缺乏区别意味着设备驱动程序可以读取:

struct {
    int csr;
    int blk;
    int bar;
    int bcr;
};

0177440->bcr = count;
0177440->blk = block;
0177440->bar = addr;
0177440->csr = READ | GO;

这可能就是告诉设备读取一些字节或块的方式。

(这也是为什么结构成员名称,如st_inoin struct stat,都以这样的前缀表示:st_ino仅表示“一些整数偏移量”,您可以将st_ino成员与任何指针一起使用,甚至可以与普通变量一起使用。前缀意味着您可以在#include没有多个标题的情况下使用它们的结构成员名称发生冲突。)

当 C 语言在 32 位和其他机器上工作时,所有这些都变得站不住脚了。C 增加了一个unsigned整数类型,而不是将指针作为无符号整数来服务,Steve Johnson 的 PCC 编译器变成unsigned了一个修饰符,可以应用于charshort以及int. 进行了大量的实验。最终,在 1989 年,C 首次使用我们现在拥有的大部分语法和语义进行了标准化(尽管新标准添加了新类型和许多函数,等等)。

一些早期的 C 语言先驱参与了 Go 的创建,尤其受到Ken Thompson的影响。维基百科页面上有一个合适的引用:

当我们三个人 [Thompson、Rob Pike 和 Robert Griesemer] 开始工作时,那是纯粹的研究。我们三个人聚在一起,决定我们讨厌 C++。[笑声] ... [回到 Go,] 我们一开始的想法是,我们三个人都必须被告知该语言的每个功能,因此不会出于任何原因将无关的垃圾放入该语言中。

正如我们在早期的 C 语言中所看到的,作为整数的指针是一种合适的无符号类型,它不仅可以保存任何指针,而且如果被视为无符号,还可以保存任何对象大小。当然,作为整数的指针不能直接用作指针,并且对于 GC 系统和并发性,我们需要语言本身具有指针。但是我们还需要能够为该语言编写运行时支持 1为此我们需要整数化指针,这也涵盖了我们对对象大小的所有需求。因此,编译器内置的一种类型涵盖了所有需求。那是尽可能简单,但并不简单


1我说“我们”,就好像我和它有什么关系一样。很明显,一旦您实现了一些运行时系统。


推荐阅读