【问题标题】:What is the size of a pointer? What exactly does it depend on?指针的大小是多少?它具体取决于什么?
【发布时间】:2014-06-04 18:59:57
【问题描述】:

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

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

【问题讨论】:

  • 指针是一种高级语言结构;理论上它可以是任何宽度。另一方面,内存地址是一种物理构造。
  • 在现代 PC 上,指针的大小取决于本机字长(32 位或 64 位)的大小。但是没有什么可以说指针必须是特定的长度或大小,甚至指针的大小必须在使用单个编译器的单个平台上是统一的。例如,指向整数的指针可能是一种大小,但指向函数的指针可能是另一种大小。
  • 我看不出这个问题太宽泛了。它有 5 个简单的子问题。一切都很容易回答,并且确实有具体的答案。请不要因为您无法回答问题而投票结束。让其他人有机会做出贡献和学习,更不用说将来谷歌了。
  • @Cheersandhth.-Alf:恕我直言,回答 OP 询问的一切会占用页面;一些子问题本身非常广泛(例如“有哪些不同类型的指针”)。也就是说,如果您准备好答案,请告诉我,我将提供剩余的重新开放投票;)
  • 如果指针命名为ptr,则其大小为sizeof ptr

标签: c++ c pointers memory


【解决方案1】:

指针是高级语言提供的抽象;理论上它可以是任何宽度。这完全是编译器的心血来潮。

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

但是,即使撇开这些不谈,仍然存在复杂性。例如:

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

【讨论】:

  • -1 “暗示 C 中所有指向对象的指针大小相同”是不正确的。
  • @Alf:C 标准说所有指向对象的指针都可以相互转换并再次转换回来(尽管对齐),这意味着它们必须支持等效范围。因此,暗示它们的大小必须相同。你不同意吗?
  • 关于您声称“C 标准说所有指向对象的指针都可以相互转换并再次转换回来”,但在 C99 中并非如此。相反,C99 声明“如果结果指针未正确对齐 50) 指向的类型,则行为未定义”。我非常怀疑 C11 在这方面有什么不同。
  • @Alf:是的,对齐是唯一的警告,AFAIK。因此,在某些架构上,指针的大小可能会相差几位。但我承认这一点,所以我会添加一个脚注,希望你能重新考虑你的 -1 ;)
  • Re 48 位虚拟地址,256 PiB 应该对任何人都足够了!(反正几年。)
【解决方案2】:

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

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

我认为当前的“语言无关”问题是无法回答的,尽管尝试了一个与语言无关的答案。

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

普通数据指针所需的最小大小取决于所指向类型的对象或不同函数的最大可能内存位置数;需要区分 n 个可能的位置 ceil(lg2(n)) 位。

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

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

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

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


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

主要是从 C++ 看到的可寻址内存范围。

但值得回顾的是,在 MS-DOS 编程中,nearfar 指针之间存在差异。 near 指针是隐含的 64K 内存段的偏移量,而 far 指针是大小的两倍,结合了段选择器和偏移量。

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


3。编译器会影响指针的大小吗?怎么样?

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

由于成员指针不是直接地址(在底层),如何表示它们以及它们有多大在很大程度上取决于编译器。

这也取决于使用的选项。


4。有哪些不同类型的指针,它们之间有何不同? (例如:函数指针和指向基本数据类型的指针有区别吗?近指针与远指针等)

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

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

以上内容实际上意味着对象指针和函数指针是不同的。例如。后者不支持地址算术。另外,成员指针不同于真指针,更类似于偏移量。

现代 C++ 不支持近与远指针。


5。语言是否对指针有任何影响。 C 与 C++

C 不支持成员指针,在这个问题中它们被视为指针。

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

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

【讨论】:

  • 删除 C/C++ 并添加与语言无关的标签是由其中一位版主完成的。我不知道我是否应该回滚。那么这个问题就会被威胁要关闭,因为之前有人指出它与C/C++无关。
  • @sudhirvyasaraja:如果有人声称它与 C/C++ 无关,那么这个人就是错误。例如,这个答案引用了当前 C++ 标准中的一些段落,以及 C++ 缺陷报告。在 SO 上,人们提出各种毫无根据的主张来支持他们的立场并不罕见(缺乏讨论支持意味着尝试处理大量看似合理的主张是不切实际的,也不是很有说服力)。
  • 这是非常以英特尔为中心的。 C++ 没有段和偏移量或远地址的概念。但这确实表明指针大小是由地址空间决定的,而不是内存大小。 (当您驳斥 Oli 提出更广泛架构假设的答案时,英特尔中心主义尤其具有讽刺意味)
  • @sudhirvyasaraja:嗯,你应该让你的问题与 C 和 C++ 相关。例如,说“指针的大小在C++中
  • @Alf:我猜你从来没有在这样一种架构上工作过,即同一内存位置存在多个地址,具有不同的读/写访问权限、不同的缓存特性等?但是等等,在你的答案中有一个——DOS 的分段地址模型。请注意,我并没有说您的答案是错误的,我只是要求您表现出一些一致性并确定您何时谈论特定架构而不是 100% 可移植 C++,因为您要求其他人这样做。
猜你喜欢
  • 2011-10-08
  • 2012-06-17
  • 2011-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多