【问题标题】:Why does unsafe.Sizeof return a uintptr?为什么 unsafe.Sizeof 返回一个 uintptr?
【发布时间】:2020-09-28 21:12:40
【问题描述】:

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

【问题讨论】:

  • unitptr 是一个整数类型,它大到可以容纳任何指针。因此uintptr 大到足以容纳任何值的大小。 uint32 在某些架构上不够大。 uint64 在某些架构上比需要的大。
  • A uintptr 不应该保存指针,它只是一个无符号指针大小的值(在不安全的用例之外,您永远不应该将实际指针保存为 uintptr)。它是唯一特定于体系结构的无符号数字类型。
  • 还因为uintptr 可以转换为unsafe.Pointer,它可以用于(不安全!)指针运算,可能会使用Sizeof 之类的东西。
  • uintptr is an integer type that is large enough to hold the bit pattern of any pointer. - uintptr 类型的官方描述。
  • 这不仅仅是一个数字。 (确实如此,但指针也是如此。)它是两个指针之间的差异(指向将由表达式创建的假设变量的开始和结束)。我们本可以添加一个新的 intptrdiff 类型,但 C 和 uintptr 的味道非常匹配。

标签: go


【解决方案1】:

在 cmets 中有很多好的答案,归结为“因为它足够大,但又不太大”。不过,我认为,从历史的角度来看这可能会有所帮助,尤其要注意这一切是如何在 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;

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

(这也是为什么结构成员名称,如struct stat 中的st_ino,都使用这样的前缀:st_ino 仅表示“某个整数偏移量”,您可以将st_ino 成员与任何指针一起使用,甚至是普通变量。前缀意味着您可以#include 多个标头而不会使其结构成员名称发生冲突。)

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

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

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

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


1我说“我们”,就好像我和它有什么关系一样。这只是显而易见的,一旦您实现了一些运行时系统。

【讨论】:

    猜你喜欢
    • 2017-06-12
    • 2011-12-17
    • 2012-11-12
    • 2017-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多