指针的大小是多少? 它究竟依赖于什么?

我在网上搜索,虽然我可以找到一些讨论,但我没有找到全面的描述。 因此,如果任何人都可以形成一个涵盖指针大小的答案,那将会有很大的帮助。 答案至少应包括以下主题

  1. 指针的大小取决于什么?
  2. 架构的哪些特性会影响指针的大小? (详细地)
  3. 编译器如何影响指针的大小?

指针是由高级语言提供的抽象; 理论上它可以是任何宽度。 这完全是编译器的奇思妙想。

实际上,它通常与底层硬件的内存地址的宽度有关,因为这通常是编译器实现的最有效的方法。 但也有例外; 例如,C ++的指向成员函数的指针没有直接映射到硬件地址,因为它需要代表两个实体(函数和类型的一些概念)。

然而,即使把它放在一边,仍然存在复杂性。 例如:

  • 在大多数现代硬件上,您的程序将使用虚拟内存地址,而不是物理地址(可能不是相同的宽度)。 除非您正在编写内核空间代码。
  • 在某些体系结构(例如x86)上,底层硬件展示了分段地址空间。 这非常复杂,但主要是由操作系统和虚拟内存系统抽象出来的。 如果您正在为真正的旧x86编写内核空间代码或代码,那么您将不得不处理它。
  • 在当前的x86-64上,(虚拟)内存地址实际上只有48位宽。
  • x86-64支持32位和64位可执行文件。
  • 您可能正在虚拟机内运行,如果需要,它也可以执行任何操作(相对于底层物理机)。

这个问题最初标记为C和C ++,而不是“语言不可知”。 作为一个与语言无关的问题,它应该被视为过于宽泛 ,但我希望OP将其恢复为原始版本1,因此我不会投票结束。 作为一个C / C ++问题,虽然显然是负责任的,但它被视为过于宽泛,然后当范围被极大地扩展到无法回答时,通过将该标记更改为与语言无关,它被重新打开为现在可以回答。

我正在回答C ++的原始问题,这里和那里散布着一些C知识。

我认为目前的“语言不可知”问题是无法回答的,尽管有一种尝试与语言无关的答案。

1.指针的大小取决于什么?

普通数据指针所需的最小尺寸取决于指向类型或不同function的对象的可能存储位置的最大数量; 为了区分n个可能的位置,需要ceil(lg2( n ))位。

因此,最小指针大小取决于最大可能的内存大小。

因此,最小指针大小也取决于指向类型的对齐。 在一些现在过时的机器上,甚至可能在一些现存的机器(大型机?)上,硬件级别可寻址的存储器单元是例如2或4个字节的字。 然后可以使用小指针来寻址字对齐的数据,而char*因此也需要更大的void*

因此,§3.9.2/ 4中的C ++ 11标准要求“类型为cv void*的对象应具有与cv char*相同的表示和对齐要求。”

C ++中的成员函数指针更类似于偏移而不是指针,并且通常比正确的指针更大。


2.架构的哪些特性会影响指针的大小? (详细地)

从C ++可以看出主要是可记录的内存范围。

但值得回顾的是,在MS-DOS编程中,一个区别在指针和指针之间。 指针是一个隐含的64K内存段的偏移量,而一个两倍大小的指针组合了一个段选择器和偏移量。

在(仍然)现代32位PC编程C和C ++指针通常类似于指针,不支持指针,这将是6个字节。 要使用这样的指针,必须使用汇编语言等其他语言。


3.编译器是否会影响指针的大小? 怎么样?

所使用的编译器和编译选项原则上可以影响指针大小,因为标准没有规定大小。 例如,它原则上可以添加信息以帮助调试。 或者如上所述,使用语言扩展可以有近距离远距离指针。

由于成员指针不是直接地址(在引擎盖下),因此编译器如何表示它们以及它们有多大。

这也取决于使用的选项。


4.什么是不同类型的指针以及它们彼此之间有何不同? (例如:函数指针和指向基本数据类型的指针之间是否存在差异?,指针与远指针之间等)

在C ++ 03中,函数指针无法转换为数据指针,反之亦然。 这种限制支持具有哈佛架构的机器,并且它支持可能的不同大小的函数指针和数据指针(例如,前者为 ,后者为 )。 在C ++ 11中, 有条件地支持这种转换,在§5.2.10/ 8中,由缺陷报告195产生 。

值得注意的是,Posix标准需要支持转换(函数指针)→( void* )和返回,例如对于dlsym函数。

上述有效意味着对象指针和函数指针是不同的。 例如,后者不支持地址算术。 此外,成员指针与正确的指针不同,更类似于偏移。

Modern C ++不支持near指针和远指针。


5.语言是否对指针有影响。 C vs C ++

C不支持成员指针,只要它们被认为是这个问题的指针。

除此之外,C ++的主要目标是能够直接使用C库,并将C标准“合并”(C ++11§17.5.1.5/ 1)到C ++标准中,这需要兼容的指针表示。

C支持限制指针,限定符restrict ,C ++不支持。 但是,这只会影响编译器对指针可能值的了解。 这意味着C编译器可能能够发出更好的优化代码。